对于容器类的功能理解:接口实现时主要的功能体现方式。Abstract类虽然实现的部分接口的功能,但是真正的容器实现并没有在Abstract类的基础上实现,而是使用的更加高效的方式。Abstract类的出现是为用户提供了方便地实现自定义容器的接口。
比如AbstractSet的实现只需要提供Size()方法和Iterator()方法,但是实际上虽然HashMap 继承了AbstractSet但是其是通过HashMap()实现的。同理的,要实现一个自定义的List,只需要给AbstractList提供一个get()方法,但是ArrayList确实通过数组实现的。
所以要理解不同容器的功能和性能,需要从两个方面理解: 第一是容器类的功能上的差异。第二是不同实现的方式的容器在性能上的差异。
List 和 Set 都是实现了与 Collection 接口的所有方法,但是在不同种类型实现的容器中,所支持的接口是可以通过UnsupportedOperationException 异常来进行选择的,特别是对于一些基于固定长度的数据结构的容器,任何的调整容器大小的方法都是不受支持的,比如Arrays.asList()方法所返回的List,Add、Remove等方法都是不受支持的。
在Arrays类内部,根据AbstractList重新定义了一个ArrayList
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
/**
* @serial include
*/
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
在AbstarctList中:
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
但是,如果将如Arrays.asList()方法所返回的List作为构造器参数生成的ArrayList将产生一个允许所有方法的容器。
Collections.unmodifiableList()同理将会产生一个unmodifiableCollection: 持有一个Collection,让后将Modify有关的方法适配。
static class UnmodifiableCollection<E> implements Collection<E>, Serializable {
private static final long serialVersionUID = 1820017752578914078L;
final Collection<? extends E> c;
UnmodifiableCollection(Collection<? extends E> c) {
if (c==null)
throw new NullPointerException();
this.c = c;
}
public boolean add(E e) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
public boolean containsAll(Collection<?> coll) {
return c.containsAll(coll);
}
public boolean addAll(Collection<? extends E> coll) {
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection<?> coll) {
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection<?> coll) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
}