Iterator和Iterable:
讲到Iterator和Iterable,不得不先提提设计模式里面的迭代器模式。
回顾文章:
我们可以看到,迭代器模式的动机在于:使得我们可以用统一的接口去遍历数据结构,而不需要知道数据结构本身的构造。这体现了面向对象设计的封装性。譬如,我们遍历一个数组需要通过"for (int index=0; index< array.length; index++)“来实现,而遍历一个链表需要用:"while(cur != null){cur = cur.next}"来实现,而使用一个Iterator类,可以把这些不同的遍历方式都封装进去next()的方法里。通过不断调用next()返回集合的下一个元素。客户端不需要知道数据结构的实现和构造,只要调用Iterator对象的方法即可。
Java已经为我们设计了Iterator和Iterable的接口。两者的区别与联系如下:
通过,一个集合类如果要实现for each语法,也就是(for class ins : collection),需要implements 一个Iterable接口。通过查看API,Iterable接口只需要实现一个方法:
这个方法需要返回一个Iterator。
而一般这个Iterator是使用内部类来创建。一般在集合类的内部,创建一个implements Iterator的内部类,然后在内部类中实现Iterator的方法。实现Iterator至少需要实现两个方法:boolean hasNext()和E next()。remove()方法可以选择实现,作为删除集合元素的备选。
假如,我需要为自己实现的链表类implements Iterable:
import java.util.Iterator;
import java.util.Iterable;
public class LinkedList<AnyType> implements Iterable<AnyType>{
private Node<AnyType> head;
public LinkedList(){
head = null;
}
public void addFirst(AnyType item){}
public void addLast(AnyType iterm){}
public boolean addAfter(AnyType key, AnyType item){}
public boolean addBefore(AnyType key, AnyType item){}
public boolean remove(AnyType key){}
/*实现Iterable接口*/
public Iterator iterator(){
return new LinkedListIterator();
}
/*返回的LinkedListIterator需要使用内部类实现*/
/*内部类一般声明为private,因为其存在的意义是供包含的类使用而已*/
private class LinkedListIterator implements Iterator<AnyType>{
/*注意实现Iterator通常添加新的成员和构造函数*/
private Node<AnyType> cur;
public LinkedListIterator(){
cur = head;//只要是非静态的内部方法都可以调用包含类的一般成员,静态则不行
}
/*实现Iterator需要至少两个方法*/
public boolean hasNext(){
return (cur.next != null);
}
public AnyType next(){
if(cur == null){
throw new NoSuchElementException();//注意考虑极端情况
}
AnyType result = cur.data;
cur = cur.next;
return result;
}
}
}
书写这些代码的时候,注意考虑空指针的情况。书写链表的实现时,addBefore和remove都要考虑prev引用的空指针情况(head == null)和代码复用(head.data.equals(key))。
而且需要注意,LinkedListIterator不需要写<AnyType>。
Comparator和Comparable:
不同于前面所述,这两者的区别只要在于前者的外部的比较器,而后者,更多的是内部的比较器。
一个集合,实现了Comparable接口,就代表其可以使用Collections.sort()来排序。细心的读者可能也知道,Collections.sort还有另外一种用法,sort(Collection exp, Comparator)。利用Comparator,实现一个外部的比较器。
对于Comparable的定义:
package java.lang;
public interface Comparable<T> {
public int compareTo(T o);
}
当前实现了Comparable的类的对象与o比较,如果大于就返回1,等于返回0,小于返回-1.
Comparator 是比较器接口。
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现Comparator接口即可。
也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。【1】
package java.util;
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
(1) 若一个类要实现Comparator接口:它一定要实现compare(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。
为什么可以不实现 equals(Object obj) 函数呢? 因为任何类,默认都是已经实现了equals(Object obj)的。 Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数;所以,其它所有的类也相当于都实现了该函数。
(2) int compare(T o1, T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。