Collections中的内部集合类
源码基于1.8.0_112
Collections中提供了大量的集合类,以代理的方式对现有的集合进行了功能上的修改。
总共有以下几类集合:
Unmodifiable:不可修改的集合类
Synchronized:同步的集合类
Checked:类型安全的集合类
Empty:空集合类
Empty:只有单个元素的集合类
由于各类以上几类集合对List、Map、Set的实现较为相似,我们只分析List。
原理:Collections中的内部集合类为传入的类作为代理,改变传入集合的行为。
UnmodifiableCollection
UnmodifiableCollection是所有Unmodifiable类的父类
UnmodifiableCollection用一个成员变量保存传入对象,然后为该对象提供代理
UnmodifiableList是UnmodifiableCollection的其中一个子类
UnmodifiableList也会用一个成员变量保存传入对象,然后为该对象提供代理
UnmodifiableCollection和UnmodifiableList各自保存一份被代理对象的引用(指向同一个对象)。
以上都是套路,之后的集合不再介绍
UnmodifiableCollection将传入的集合修包装成一个不可变的集合。
代码
/**
* 所有Unmodifiable内部类的父类
* @param <E>
*/
static class MyUnmodifiableCollection<E> implements Serializable {
// 序列化ID
private static final long serialVersionUID = 1820017752578914078L;
// 存储集合类
final Collection<? extends E> c;
// 构造函数需要传入一个集合类
MyUnmodifiableCollection(Collection<? extends E> c) {
if (c == null)
throw new NullPointerException();
this.c = c;
}
// 实现行为相同的方法,以代理的方式访问传入的集合类
public int size() {
return c.size();
}
public boolean isEmpty() {
return c.isEmpty();
}
public boolean contains(Object o) {
return c.contains(o);
}
public Object[] toArray() {
return c.toArray();
}
public <T> T[] toArray(T[] a) {
return c.toArray(a);
}
public String toString() {
return c.toString();
}
// 修改操作抛出UnsupportedOperationException异常
public boolean add(E e) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
}
/**
* List实现类
* @param <E>
*/
static class MyUnmodifiableList<E> extends MyUnmodifiableCollection<E> {
private static final long serialVersionUID = -283967356065247728L;
// 存储集合
final List<? extends E> list;
// 需要一个传入List来构建MyUnmodifiableList
MyUnmodifiableList(List<? extends E> list) {
// 调用父类构造函数
super(list);
// 子类赋值
this.list = list;
}
// 代理访问方法
public E get(int index) {
return list.get(index);
}
public int indexOf(Object o) {
return list.indexOf(o);
}
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
// 所有修改的操作,都会被禁止
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
public boolean addAll(int index, Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
}
SynchronizedCollection
SynchronizedCollection应该算是一个比较重的的集合,他会把传入的集合包装成一个线程安全的集合类
SynchronizedCollection和Vector做一个比较:
1. SynchronizedCollection具有更加合理的结构
2. SynchronizedCollection可以自定义锁对象
3. SynchronizedCollection没有对迭代器做同步处理。Vector迭代每次的next操作都会加锁,这样会频繁的加锁,性能可想而知。我们更希望的是,在迭代前加锁,将整个迭代过程放在同步块中,这样就只会进行一次加锁操作,SynchronizedCollection正是希望我们会这么做。
4. 总之SynchronizedCollection更加的自由,更加推荐被使用。
总结:再需要使用同步集合的时候,我们可以选择SynchronizedCollection和CopyOnWriteArrayList
SynchronizedCollection:一般情况下使用,注意自行同步部分方法
CopyOnWriteArrayList:集合修较少被修改的情况下使用
代码
static class SynchronizedCollection<E> implements Serializable {
final Collection<E> c; // Backing Collection
// 锁对象
final Object mutex; // Object on which to synchronize
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}
SynchronizedCollection(Collection<E> c, Object mutex) {
this.c = Objects.requireNonNull(c);
this.mutex = Objects.requireNonNull(mutex);
}
// 对操作进行加锁处理
public int size() {
synchronized (mutex) {return c.size();}
}
// 迭代器未进行同步
public Iterator<E> iterator() {
return c.iterator(); // Must be manually synched by user!
}
public boolean add(E e) {
synchronized (mutex) {return c.add(e);}
}
public boolean remove(Object o) {
synchronized (mutex) {return c.remove(o);}
}
}
static class SynchronizedList<E> extends SynchronizedCollection<E>{
final List<E> list;
SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
SynchronizedList(List<E> list, Object mutex) {
super(list, mutex);
this.list = list;
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
}
public ListIterator<E> listIterator() {
return list.listIterator(); // Must be manually synched by user
}
}
CheckedCollection
CheckedCollection必须指定类型,将传入对象包装成一个类型安全的集合
CheckedCollection插入时会检查类型,确保集合是类型安全的
代码
/**
* 类型安全的集合
*
* @param <E>
*/
static class CheckedCollection<E> implements Serializable {
private static final long serialVersionUID = 1578914078182001775L;
final Collection<E> c;
final Class<E> type;
@SuppressWarnings("unchecked")
E typeCheck(Object o) {
if (o != null && !type.isInstance(o))
throw new ClassCastException(badElementMsg(o));
return (E) o;
}
private String badElementMsg(Object o) {
return "Attempt to insert " + o.getClass() +
" element into collection with element type " + type;
}
// 必须制定类型
CheckedCollection(Collection<E> c, Class<E> type) {
this.c = Objects.requireNonNull(c, "c");
this.type = Objects.requireNonNull(type, "type");
}
public int size() {
return c.size();
}
public boolean remove(Object o) {
return c.remove(o);
}
}
static class CheckedList<E> extends CheckedCollection<E> {
private static final long serialVersionUID = 65247728283967356L;
final List<E> list;
CheckedList(List<E> list, Class<E> type) {
super(list, type);
this.list = list;
}
public E get(int index) {
return list.get(index);
}
public E remove(int index) {
return list.remove(index);
}
public E set(int index, E element) {
return list.set(index, typeCheck(element));
}
// 插入时需要验证类型
public void add(int index, E element) {
list.add(index, typeCheck(element));
}
}
EmptyList
EmptyList提供一个空的对象,对象不可修改。
Collections中有一个EMPTY_LIST成员变量,该变量为static
例如:某个函数返回一个List,如果返回的List不存在。那么我们不应该返回null,而是使用一个空对象代替。这时候我们可以使用return Collections.EMPTY_LIST;
代码
// Collections成员变量
public static final List EMPTY_LIST = new EmptyList<>();
/**
* 空对象
*/
private static class EmptyList<E> extends AbstractList<E> implements RandomAccess, Serializable {
public int size() {return 0;}
public boolean isEmpty() {return true;}
public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
SingletonList
SingletonList内只允许存储一个元素,该元素在List初始化时确定。
代码
/**
* 单元素对象
* @param <E>
*/
private static class SingletonList<E> extends AbstractList<E> implements RandomAccess, Serializable {
private static final long serialVersionUID = 3093736618740652951L;
private final E element;
// 初始化时传入一个元素
SingletonList(E obj) {
element = obj;
}
public int size() {
return 1;
}
// 只允许返回第一个元素
public E get(int index) {
if (index != 0)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: 1");
return element;
}
}
总结
Collections中的内部集合类对原始集合类做了一些扩展和定制,毕竟Collections算是一个工具类。