Using Java 8 Lambda expressions for collections internal iteration
- Details
- Written by Nam Ha Minh
- Last Updated on 17 June 2019   |   Print Email
List<String> fruits = Arrays.asList("apple", "banana", "lemon", "orange"); for (String aFruit : fruits) { System.out.println(aFruit); }Doing this way, we take each element out of the collection for iterating from the first to the end. Thus it is called “external iteration”.We know that in Java, all the collection interfaces (List, Set, Queue, etc) have the Iterable as their super interface. And since Java 8, the Iterable interface introduces a new method:
void forEach(Consumer<? super T> action)
According to its Javadoc, this method “Performs the given action on the contents of theIterable
, in the order elements occur when iterating, until all elements have been processed or the action throws an exception.” - That means we can use this method for iterating over a collection, and perform the given action on each element, by passing a “behavior” - a class that implements the Consumer interface. The Javadoc also states that, internally, implementation of the forEach() method should iterate over its elements in the following fashion:for (T t : thisList) action.accept(t);With that in mind, the previous example can be re-written as follows:
fruits.forEach(new Consumer<String>() { public void accept(String s) { System.out.println(s); } });Here, we create an anonymous inner class which is passed into the forEach() method. Obviously, this anonymous class must implement the Consumer interface and override its accept() method.Now, because the Consumer is a functional interface with the functional method accept(), we can replace the code of the anonymous class above with a Lambda expression like this:
fruits.forEach(s -> System.out.println(s));Here, the Lambda expression is an anonymous representation of a function descriptor of a functional interface. Interestingly, we can use static method reference to make the code even more concise:
fruits.forEach(System.out::println);
class Fruit { static void countWord(String s) { System.out.println(s.length()); } }Now, we know that it’s legal to pass a static method reference to the forEach() method like this:
fruits.forEach(Fruit::countWord);Using the forEach() method as in the above examples is referred as “internal iteration” - not because the way of iteration is different than the iteration method using “classic enhanced for loop”. It’s called internal iteration because the collection does the iteration itself, instead of having the external code takes every element out of the collection. And more importantly, the forEach() method allows us to use Lambda expressions and method reference syntax to pass in the action would be performed for each element in the collection. That makes our code more concise, more dynamic and functional.For your convenient, we assemble all the code snippets presented above into a sample program so that you can run and experiment yourself with the concepts. Here’s the code:
package net.codejava.lambda; import java.util.*; import java.util.function.*; public class LambdaIterationExample { public static void main(String[] args) { List<String> fruits = Arrays.asList("apple", "banana", "lemon", "orange"); System.out.println("==== Classic enhanced for loop ===="); for (String aFruit : fruits) { System.out.println(aFruit); } System.out.println("\n==== Anonymous class ===="); fruits.forEach(new Consumer<String>() { public void accept(String s) { System.out.println(s); } }); System.out.println("\n==== Lambda Expression ===="); fruits.forEach(s -> System.out.println(s)); System.out.println("\n==== Lambda Method Reference ===="); fruits.forEach(System.out::println); System.out.println("\n==== Lambda Method Reference 2 ===="); fruits.forEach(Fruit::countWord); } } class Fruit { static void countWord(String s) { System.out.println(s.length()); } }Output of the program:
==== Classic enhanced for loop ==== apple banana lemon orange ==== Anonymous class ==== apple banana lemon orange ==== Lambda Expression ==== apple banana lemon orange ==== Lambda Method Reference ==== apple banana lemon orange ==== Lambda Method Reference 2 ==== 5 6 5 6API References
- java.util.function.Consumer interface Javadoc
- java.util.Iterable interface Javadoc
- Java SE 8: Lambda Quick Start
- Maurice Naftalin’s Lambda FAQ
Other Java Collections Tutorials:
- Java Set Tutorial
- Java Map Tutorial
- Java List Tutorial and
- Java Queue Tutorial
- Understanding equals() and hashCode() in Java
- Understanding Object Ordering in Java with Comparable and Comparator
- 18 Java Collections and Generics Best Practices
Comments