Monday, September 30, 2019

Java 8 – Iterable.forEach, Iterator.remove methods

New default method forEach() added to the Iterable Interface in Java 8

Iterable interface is a commonly extended interface among the Collections interfaces as it provides the ability to iterate over the members of a collection. Collection, List and Set are among the important Collections interfaces that extend Iterable, apart from other interfaces.

Collections classes extend Iterable
Java 8’s new Iterable.forEach() method has the following signature –

default void forEach(Consumer<? super T> action)
Where,
     – action is the only parameter and is an instance of a Consumer Functional Interface
     – forEach() is implemented in the Iterable interface itself as a default method.

Iterable.forEach() method ‘consumes’ all the elements of the iterable collection of elements passed to it. The logic for consumption is passed to the method as an instance of a Consumer functional interface. An important point to note is that the forEach method iterates internally over the collection of elements passed to it rather than externally. You can read about declarative internal iterators and how they differ from commonly used external iterators in this tutorial here.

Let us now take a look at Java code showing how to use Iterable.forEach() method for consuming the elements of an Iterable collection –

Java 8 code to iterate and consume using Iterable.forEach() method

package com.javabrahman.java8.collections;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class IterableForEachExample {
  public static void main(String args[]){
    List<Integer> intList= Arrays.asList(12,25,9);
    System.out.println("List elements printed using Iterable.forEach");
    intList.forEach(System.out::println);
   
    Set<Integer> intSet=new HashSet<>();
    intSet.add(50);
    intSet.add(1);
    System.out.println("Set elements printed using Iterable.forEach");
    intSet.forEach(System.out::println);
  }
}

 OUTPUT of the above code

List elements printed using Iterable.forEach
12
25
9
Set elements printed using Iterable.forEach
1
50
Explanation of the code


A List of primitive ints, named intList, is created using the Arrays.asList() method.
forEach() method is invoked on the List instance – intList. As we read above, List inherits the forEach() method’s default implementation from Iterable interface.
We pass a method reference to System.out.println() method, which is a Consumer type of function, as parameter to the forEach() method.

forEach() method internally iterates and consumes, or prints, the elements of intList.
Next we created an instance of a Set, named intSet, by using its concrete implementation HashSet.
Set also inherits Iterable. Hence, we are able to print the elements in intSet using the forEach() method similar to the way we did with intList.


New default method remove() added to Iterator interface in Java 8


Prior to Java 8, implementing Iterator interface without the support for remove() method implied that the designers had to override the method and throw an UnsupportedOperationException. Such an override was commonly done and over the years had become kind of staple in Iterator implementations not supporting the remove operation.

With Java 8 arrived the feature of adding default implementations of methods in interfaces itself. Java designers have used this new feature and added a default implementation of the remove() method in the Iterator interface itself which throws UnsupportedOperationException.

As a result, the practice of overriding the remove() method, whenever it wasn’t supported, has now been inverted to overriding the remove() method only when remove functionality has to be implemented. This has removed the unnecessary overhead of overriding and throwing the UnsuportedOperationException everytime when implementing an Iterator without remove functionality.

The default implementation of remove() method in Java 8’s Iterable is as shown below –

default void remove() {
  throw new UnsupportedOperationException("remove");
}

As you can see in the above code, the default implementation of Iterator.remove() method just throws an UnsupportedOperationException with message "remove".

No comments:

Post a Comment