下面3个示例重点阐述:方法与实现的解耦
,也就是将队列与消费队列的方法连接在一起耦合度最小的方式。
标准 C++ 类库中并没有其容器的任何公共基类———容器之间的所有共性都是通过迭代器达成的。而Java中,将两种方法绑定到了一起,因为实现公共基类Collection就意味着需要提供iterator()方法:
如下所示,两个版本的display()方法都可以使用Map或Collection的子类型来工作,而且Collection接口和Iterator都可以将display()方法与底层容器的特定实现解耦。
//: holding/InterfaceVsIterator.java
package holding;
import typeinfo.pets.*;
import java.util.*;
public class InterfaceVsIterator{
//当你要实现一个Collection的外部类时可能非常困难,因此使用Iterator就会变得非常吸引人;使用此种方法的Collection通常是自建类,具体如下CollectionSequence.java所示。
public static void display(Iterator<Pet> it){
while(it.hasNext()){
Pet p = it.next();
System.out.print(p.id()+":"+p+" ");
}
System.out.println();
}
//Collection是Iterable类型,因此,可以使用foreach结构;使用此种方法的Collection通常是已有类
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.arrayList(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); //0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
display(petSet); //0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
display(petList.iterator()); //0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
display(petSet.iterator()); //0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
System.out.println(petMap); //{Ralph=Rat, Eric=Manx, Robin=Cymric, Lacey=Mutt, Britney=Pug, Sam=Cymric, Spot=Pug, Fluffy=Manx}
System.out.println(petMap.keySet()); //[Ralph, Eric, Robin, Lacey, Britney, Sam, Spot, Fluffy]
display(petMap.values()); //0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
display(petMap.values().iterator()); //0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
}
}
我们通过继承一个持有Pet对象的类来创建一个Collection的实现,有两种选择:第1是通过实现Collection接口,太麻烦,要实现的接口太多;第2是通过继承AbstractCollection,只需要实现iterator()和size():
//: holding/CollectionSequence.java
package holding;
import typeinfo.pets.*;
import java.util.*;
public class CollectionSequence extends AbstractCollection<Pet>{
private Pet[] pets = Pets.createArray(8);
@Override
public Iterator<Pet> iterator() {
return new Iterator<Pet>(){
private int index=0;
@Override
public boolean hasNext() {
return index<pets.length;
}
@Override
public Pet next() {
return pets[index++];
}
//Iterator中有一个remove()方法是一个“可选操作”,你将在第17章中了解它,这里不必实现它,如果你调用它,它会抛出异常。
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public int size() {
return pets.length;
}
public static void main(String args[]){
CollectionSequence c = new CollectionSequence();
//注意,第1例中的2种方法在此外都可以使用
InterfaceVsIterator.display(c); //0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
InterfaceVsIterator.display(c.iterator()); //0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
}
}
如果你的类已经继承了其他的类,那么你就不能再继承AbstractCollection了,在这种情况下,要实现Collection,就必须实现该接口的所有方法;但还有另一种方法就是为此类创建一个迭代器,就可以使用上面的display(Iterator it)方法了,如下所示:
//: holding/NonCollectionSequence.java
package holding;
import typeinfo.pets.*;
import java.util.*;
class PetSequence {
protected Pet[] pets = Pets.createArray(8);
}
public class NonCollectionSequence extends PetSequence {
public Iterator<Pet> iterator() {
return new Iterator<Pet>() {
private int index = 0;
public boolean hasNext() {
return index < pets.length;
}
public Pet next() { return pets[index++]; }
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
};
}
public static void main(String[] args) {
NonCollectionSequence nc = new NonCollectionSequence();
//注意,第1例中的2种方法在此外都并不是都能使用了
InterfaceVsIterator.display(nc.iterator());
}
} /* Output:
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx
*///:~
如果你需要演示,请下载文中用到的 typeinfo java类文件.
说明:本文是对第四版Java编程思想第11.12节Collection和Iterator的归纳整理。