Collection is the root interface common to all sequence collections. Note Interface Collection (since 1.2) extends Iterable Interface(since 1.5).
case 1:
// collections/InterfaceVsIterator.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
import java.util.*;
import typeinfo.pets.*;
public class InterfaceVsIterator {
public static void display(Iterator<Pet> it) {
System.out.println("Iterator<Pet>:");
while (it.hasNext()) {
Pet p = it.next();
System.out.print(p.id() + ":" + p + " ");
}
System.out.println();
}
public static void display(Collection<Pet> pets) {
for (Pet p : pets) {
System.out.print(p.id() + ":" + p + " ");
}
System.out.println();
}
public static void main(String[] args) {
List<Pet> petList = Pets.list(8);
Set<Pet> petSet = new HashSet<>(petList);
Map<String, Pet> petMap = new LinkedHashMap<>();
String[] names = ("Ralph, Eric, Robin, Lacey, " + "Britney, Sam, Spot, Fluffy").split(", ");
for (int i = 0; i < names.length; i++) {
petMap.put(names[i], petList.get(i));
}
display(petList);
display(petSet);
display(petList.iterator());
display(petSet.iterator());
System.out.println(petMap);
System.out.println(petMap.keySet());
display(petMap.values());
display(petMap.values().iterator());
}
}
/* My Output:
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
Iterator<Pet>:
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
Iterator<Pet>:
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
{Ralph=Rat, Eric=Manx, Robin=Cymric, Lacey=Mutt, Britney=Pug, Sam=Cymric, Spot=Pug, Fluffy=Manx}
[Ralph, Eric, Robin, Lacey, Britney, Sam, Spot, Fluffy]
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
Iterator<Pet>:
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
*/
case 2:
// collections/CollectionSequence.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
import java.util.*;
import typeinfo.pets.*;
public class CollectionSequence extends AbstractCollection<Pet> {
private Pet[] pets = Pets.array(8);
@Override
public int size() {
return pets.length;
}
@Override
public Iterator<Pet> iterator() {
return new Iterator<Pet>() { // [1] remove Pet in the <>, it produces compile Error
private int index = 0;
@Override
public boolean hasNext() {
return index < pets.length;
}
@Override
public Pet next() {
return pets[index++];
}
@Override
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
};
}
public static void main(String[] args) {
CollectionSequence c = new CollectionSequence();
InterfaceVsIterator.display(c);
InterfaceVsIterator.display(c.iterator());
}
}
/* Output:
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
*/
- [1] We might think, since iterator() returns Iterator<Pet> , that the anonymous inner class definition could use the diamond syntax and Java could infer the type. But that doesn’t work; the type inference is still quite limited.
This example shows that if you implement Collection, you also implement iterator(), and just implementing iterator() alone requires only slightly less effort than inheriting from AbstractCollection.
for-in and Iterators
// collections/ForInCollections.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// All collections work with for-in
import java.util.*;
public class ForInCollections {
public static void main(String[] args) {
Collection<String> cs = new LinkedList<>();
Collections.addAll(cs, "Take the long way home".split(" "));
for (String s : cs) {
System.out.print("'" + s + "' ");
}
}
}
/* Output:
'Take' 'the' 'long' 'way' 'home'
*/
Since cs is a Collection, this code shows that working with for-in is a characteristic of all Collection objects. The reason this works is that Java 5 introduced an interface called Iterable containing an iterator() method that produces an Iterator.
When implements Iterable, we can use for-in like:
// collections/IterableClass.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Anything Iterable works with for-in
import java.util.*;
public class IterableClass implements Iterable<String> {
protected String[] words =
("And that is how " + "we know the Earth to be banana-shaped.").split(" ");
@Override
public Iterator<String> iterator() {
return new Iterator<String>() {
private int index = 0;
@Override
public boolean hasNext() {
return index < words.length;
}
@Override
public String next() {
return words[index++];
}
@Override
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
};
}
public static void main(String[] args) {
for (String s : new IterableClass()) { // diff
System.out.print(s + " ");
}
}
}
/* Output:
And that is how we know the Earth to be banana-shaped.
*/
Array is not automatically an Iterable, we must do it by hand.
// collections/ArrayIsNotIterable.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
import java.util.*;
public class ArrayIsNotIterable {
static <T> void test(Iterable<T> ib) {
for (T t : ib) {
System.out.print(t + " ");
}
}
public static void main(String[] args) {
test(Arrays.asList(1, 2, 3));
String[] strings = {"A", "B", "C"};
// An array works in for-in, but it's not Iterable:
// test(strings); // [1]
// You must explicitly convert it to an Iterable:
test(Arrays.asList(strings));
}
}
/* Output:
1 2 3 A B C
*/
[1]'s compile error:
collections/ArrayIsNotIterable.java:19: error: method test in class ArrayIsNotIterable cannot be applied to given types;
test(strings);
^
required: Iterable<T>
found: String[]
reason: cannot infer type-variable(s) T
(argument mismatch; String[] cannot be converted to Iterable<T>)
where T is a type-variable:
T extends Object declared in method <T>test(Iterable<T>)
1 error
references:
1. On Java 8 - Bruce Eckel
2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/collections/InterfaceVsIterator.java
4. https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html
5. https://docs.oracle.com/javase/8/docs/api/java/util/AbstractCollection.html
6. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/collections/ForInCollections.java
7. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/collections/IterableClass.java
8. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/collections/ArrayIsNotIterable.java
9. https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html