Appendix: Java's Lambda
Lambdas are anonymous functions. They were added to Java since 2014 with the release of JDK 8. Lambdas can be used in any place a "Single Abstract Method" (SAM) was used before.
Let's showcase the use of Lambdas through a demo.
public class LambdaDemo {
public static void main(String[] args) {
}
private static List<Course> getSampleCourses() {
List<Course> courses = new ArrayList<>();
courses.add(new Course("EN.601.421", "Object-Oriented Software Engineering"));
courses.add(new Course("EN.601.226", "Data Structures"));
courses.add(new Course("EN.601.621", "Object-Oriented Software Engineering"));
return courses;
}
}
We start with using anonymous inline classes.
private static void usingAnonymousInlineClass() {
List<Course> courses = getSampleCourses();
Collections.sort(courses, new Comparator<Course>() {
@Override
public int compare(Course c1, Course c2) {
return c1.getOfferingName().compareTo(c2.getOfferingName());
}
});
for (Course c: courses) {
System.out.println(c);
}
}
Call usingAnonymousInlineClass
in main
and it must print out the sample courses sorted by offeringName
.
EN.601.226 Data Structures
EN.601.421 Object-Oriented Software Engineering
EN.601.621 Object-Oriented Software Engineering
Alright, let's do the same thing with a lambda function!
private static void usingLambdaInLongForm() {
List<Course> courses = getSampleCourses();
Collections.sort(courses, (Course c1, Course c2) -> {
return c1.getOfferingName().compareTo(c2.getOfferingName());
});
for (Course c: courses) {
System.out.println(c);
}
}
Look at the second argument to the Collections.sort
method:
(Course c1, Course c2) -> {
return c1.getName().compareTo(c2.getName());
}
It is a function written in Java's Lambda notation. It is just syntax sugar for anonymous inline implementation of Comparator
.
You've used syntax sugar before: this enhanced for loop
for (Course c: courses) {
System.out.println(c);
}
is syntax sugar for the use of an iterator:
Iterator<Course> it = courses.iterator();
while (it.hasNext()) {
Course c = it.next();
System.out.println(c);
}
Back to Lambdas, let's simplify our lambda expression:
private static void usingLambdaInShortForm() {
List<Course> courses = getSampleCourses();
Collections.sort(courses, (c1, c2) -> c1.getOfferingName().compareTo(c2.getOfferingName()));
courses.forEach(course -> System.out.println(course));
}
Let's focus on the Lambda function:
(c1, c2) -> c1.getOfferingName().compareTo(c2.getOfferingName()));
Notice you don't need to specify the data type of arguments! Moreover, when the body of your lambda function is a single statement, you can eliminate the {
}
and the return
keyword.
Also note the use of the forEach
method:
courses.forEach(course -> System.out.println(course));
The forEach
is a function that takes a Lambda function as argument.
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.
As you know by now, we use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but calling an existing method. In such a case, 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.
private static void usingMethodReferences() {
List<Course> courses = getSampleCourses();
Collections.sort(courses, Comparator.comparing(Course::getOfferingName));
courses.forEach(System.out::println);
}
Here is the entire demo program:
Here are some useful links if you want to learn more about Java's Lambda functions: