Collection接口
Java类库中,集合类的基本接口是Collection接口,两个基本方法:
public interface Collection<E>{
boolean add(E element);
Iterator<E> iterator();
......
}
add方法用于向集合中添加元素,如果元素确实改变了集合就返回true,否则没有变化就是false。
iterator方法用于返回一个实现了Iterator接口的对象,使用迭代器对象依次访问集合中的元素。
迭代器
Iterator接口包含4个方法:
public interface Iterator<E>{
E next();
boolean hasNext();
void remove();
default void forEachRemaining(Consumer<? super E> action)
}
通过反复调用next方法,可以逐个访问集合中的每个元素,但是到达集合的末尾,next方法将抛出一个NoSuchElementException,因此需要在调用next之前调用hasNext方法,如果迭代器对象还有多个可以访问的元素,这个方法就返回true,如果想要查看集合的所有元素,就请求一个迭代器,当hasNext返回true时就反复的调用next方法,例如:
Collection<String> c = ...;
Iterator<String> iter = c.iterator();
while(iter.hasNext()){
String element = iter.next();
//用元素做些什么
}
或者用foreach简练表示循环:
for(String element : c){
//用元素做些什么
}
foreach可以处理任何实现了Iterable接口的对象,这个接口只包含一个抽象方法:
public interface Iterable<E>{
Iterator<E> iterator();
}
Collection接口拓展了Iterable接口,因此,任何标准库中的任何集合都可以使用foreach。
不写循环,可以调用forEachRemaining方法并提供一个lambda表达式(会处理一个元素),将对迭代器的每一个元素调用这个lambda表达式,直到再没有元素为止。
iterator.forEachRemaining(element -> do something with element);
访问顺序,ArrayList从索引0开始,自增1,访问HashSet是随机顺序,但能遍历所有元素,对于计算等也不重要。
注释:Iterator和Enumeration接口方法作用一样,但后者名字累赘,引入了较短方法名的新接口。
可以认为Java迭代器位于两个元素之间,当调用next时,迭代器就越过下一个元素,并返回刚刚越过的那个元素的引用。
注释:这里有一个推论,可以将Iterator.next与InputStream.read看成等效的,从数据流中读取一个字节,就会自动地消耗掉这个字节,下一次调用read将会消耗并返回输入的下一个字节。
Iterator接口的remove方法将会删除上次调用next方法时返回的元素,想要删除指定位置的元素,仍然要越过这个元素。
Iterator<String> it = c.iterator();
it.next();
it.remove();
next方法和remove方法调用之间存在依赖性,如果调用remove之间没有调用next,将是不合法的,抛出IllegalStateException异常。
想删除相邻的两个元素,不能这样调用:
it.remove();
it.remove();
必须先调用next越过将要删除的元素。
it.remove();
it.next();
it.remove()
泛型实用方法
由于Collection与Iterator都是泛型接口,意味着你可以编写处理任何集合类型的使用方法,例如,检测任意集合是否包含指定元素的泛型方法:
public static <E> boolean contains(Collection<E> c,Object obj){
for(E e : c){
if(e.equals(obj)) return true;
return false;
}
}
Java类库设计者认为,这些实用方法中有一些非常有用,应该给它们提供给用户使用,这样,类库使用者就不必自己重新构建这些方法了,contains就是这样一个使用方法。事实上,Collection接口声明了很多有用的方法,所有的实现类必须提供这些方法,下面列举其中的一部分:
int size()
boolean isEmpty()
boolean contains(Object obj)
boolean containsAll(Collection<?> c)
boolean equals(Object other)
boolean addAll(Collection<? extends E> from)
boolean remove(Object obj)
boolean removeAll(Collection<?> c)
void clear()
boolean retainAll(Collection<?> c)
Object[] toArray()
<T> T[] toArray(T[] arrayToFill)
当然,如果实现Collection接口的每一个类都要提供如此多的例行方法,这很烦人,为了更容易实现这个接口,Java类库提供了一个类AbstractCollection,保持基础方法size和iterator为抽象方法,实现了其他的方法。
具体集合类可以拓展这个抽象类,提供迭代器方法,contains方法也由超类实现,若由不同需求或更高效,可以重写。
这种做法已经过时,这些方法最好是Collection接口的默认方法,但实际不是这样,不过增加了很多流处理相关的方法。还有一个有用的方法:
default boolean removeIf(Predicate filter),用于删除满足某个条件的元素。
java.util.Collection 1.2
- Iterator iterator(),返回访问集合的各个元素的迭代器。
- int size(),返回当前存储在集合中的元素个数。
- boolean isEmpty(),如果集合没有元素,返回true。
- boolean contains(Object obj),集合是否包含某元素。
- boolean containsAll(Collection c),集合是否包含某集合。
- boolean add(E element),添加元素到集合中,改变了集合,返回true。
- boolean addAll(Collection other),将集合添加到本集合中。
- boolean equals(Object other),重写相等方法
- boolean remove(Object obj),从集合中删除对象
- boolean removeAll(Collection c),删除某集合中的元素
- default boolean removeIf(Predicate filter),8,有则删除
- void clear(),清空集合
- boolean retainAll(Collection c),删除与参数集合不同的元素。
- Object[] toArray(),集合中元素以数组形式返回。
- T[] toArray(T[] arrayToFill),参数数组大时,将本集合填入剩余空间填null,若小,分配新数组,类型与参数数组相同,长度是集合长度,填充元素。
java.util.Iterator 1.2
- boolean hasNext(),存在可访问元素,返回true。
- E next(),返回想要访问的下一个对象,到达集合尾部,抛出异常。
- void remove(),删除上次访问的对象,与上一个方法配合使用,若已被删除或者没有元素,则抛出异常。
- default void forEachRemaining(Consumer action) 8,访问剩余元素,并传递指定动作,直到没有更多元素或者动作抛出异常。