Q1. What are the differences between Iterator<T> Vs Iterable<T>?
A1. The “Iterable” was introduced to be able to use in the “foreach” loop. A class implementing the Iterable interface can be iterated over. For example,
1 |
public interface Collection<E> extends Iterable<E> |
Hence, it can be used in the foreach loop
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.Arrays; import java.util.List; public class IterableVsIterator { public static void main(String[] args) { //numbers is iterable as List<E> extends Collection<E> //Collection<E> extends Iterable<E> List<Integer> numbers = Arrays.asList(new Integer[]{1,2,3,4}); for (Integer integer : numbers) { System.out.println(integer); } } } |
The Iterable
1 |
Iterator<T> iterator() |
So, what happens in the foreach loop?
What is an Iterator()?
Iterator is class that manages iteration over an Iterable. It maintains a state of where we are in the current iteration, and knows what the next element is and how to get it.
Here is the Iterator() API methods.
Iterable can be rewound
You can rewind an Iterable by getting a new iterator() from the Iterable. But an Iterator only has the next() method. So, an Iterable is handy if you want to traverse the elements more than once.
Q2. How do you get an Iterable in Java 8 to be used in a foreach loop?
A2. In Java 8, when you call the double “::” notation as shown below, you get an Iterable from the Stream.
So, given a Stream s, the following results in an Iterable:
1 |
s::iterator |
If you want to use this directly in an enhanced-for loop, you have to apply a cast in order to establish a target type for the method reference.
Here is the complete code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package com.read.file; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; public class MyFileReader { public static void main(String[] args) { Path file = null; try { //read from the classpath URL url = MyFileReader.class.getResource("readme.txt"); file = Paths.get(url.toURI()); //Java 8: Stream class Stream<String> lines = Files.lines( file, StandardCharsets.UTF_8 ); for( String line : (Iterable<String>) lines::iterator) { System.out.println("read=" + line); } } catch (Exception e){ e.printStackTrace(); } } } |
Here is Iterator and Iterable in action via a custom Iterable class
This is the Iterator design pattern in action.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import java.util.Iterator; public class MyIterable<T> implements Iterable<T> { public T[] a= null; public MyIterable(T[] array){ this.a = array; } @Override public Iterator<T> iterator() { return new Iterator<T>() { private int count=0; public boolean hasNext(){ return count < a.length; } public T next(){ System.out.println("Invoking next()"); return a[count++]; } public void remove(){ throw new UnsupportedOperationException(); } }; } } |
Now, using the above class
1 2 3 4 5 6 7 8 9 10 |
public class IterableVsIterator { public static void main(String[] args) { String[] technologies = {"Java", "JEE", "XML"}; MyIterable<String> entries = new MyIterable<String>(technologies); for (String tech : entries) { System.out.println(tech); } } } |
Output:
1 2 3 4 5 6 |
Invoking next() Java Invoking next() JEE Invoking next() XML |
The “Invoking next()” is printed from the iterator() anonymous class’s next() method.