Skip to content

Interlude: Java Lambdas

Setting the scene!

Lambdas are anonymous functions. They were added to Java since Java 8 was released. Lambdas can be used in any place a Single Abstract Method was used before.

Let's showcase the use of Lambdas through a demo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@SuppressWarnings("All")
public class LambdaDemo {

  public static void main(String[] args) {

  }

  private static List<Course> getSampleCourses() {
    List<Course> courses = new ArrayList<>();
    courses.add(new Course("OOSE", "jhu-oose.com"));
    courses.add(new Course("Intro OS", "jhu-os.com"));
    courses.add(new Course("Data Structures", "jhu-ds.com"));
    return courses;
  }
}

We start with using anonymous inline classes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
private static void usingAnonymousInlineClass() {
    List<Course> courses = getSampleCourses();
    Collections.sort(courses, new Comparator<Course>() {
        @Override
        public int compare(Course c1, Course c2) {
            return c1.getName().compareTo(c2.getName());
        }
    });

   for (Course c: courses) {
     System.out.println(c);
   }
}

Call usingAnonymousInlineClass in main and it must print out the sample courses sorted by name.

Lambda expression

Alright, let's do the same thing with a lambda function!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
private static void usingLambdaInLongForm() {
    List<Course> courses = getSampleCourses();
    Collections.sort(courses, (Course c1, Course c2) -> {
        return c1.getName().compareTo(c2.getName());
    });

    for (Course c: courses) {
        System.out.println(c);
    }
}

The following is syntax sugar for anonymous inline implementation of Comparator.

1
2
3
(Course c1, Course c2) -> {
    return c1.getName().compareTo(c2.getName());
}

You've used syntax sugar before: the enhanced for loop is syntax sugar for looping through the use of an iterator:

1
2
3
4
5
Iterator<Course> it  = courses.iterator();
while (it.hasNext()) {
    Course c = it.next();
    System.out.println(c);
}

Bak to Lambdas, let's simplify our lambda expression:

1
2
3
4
5
6
private static void usingLambdaInShortForm() {
    List<Course> courses = getSampleCourses();
    Collections.sort(courses, (c1, c2) -> c1.getName().compareTo(c2.getName()));

    courses.forEach(course -> System.out.println(course));
}
  • You don't need to specify the data type of arguments.
  • When the body of your lambda function is a single statement, you can eliminate the { } and the return keyword.

Also note the use of forEach method:

1
courses.forEach(course -> System.out.println(course));

We came a long way out of our comfort zone; if this is new to you, your head is probably spinning! But since we came so far, let's throw one more ingredient in the mix: Method References.

Method References

You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it's often clearer to refer to the existing method by name. Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.

1
2
3
4
5
private static void usingMethodReferences() {
    List<Course> courses = getSampleCourses();
    Collections.sort(courses, Comparator.comparing(Course::getName));
    courses.forEach(System.out::println);
}