视图并非新构建集合,而是对原集合对象进行操作。
视图只是包装了接口,只能调用接口的方法。
1.轻量级集合包装器
- 1)Arrays.asList 数组->视图对象(只能get/set,不能add/remove)
- 2)Collections.nCopies对象只存储一次,不可修改
Collections.singletonSet
Collections.singletonList
Collections.singletonMap
...
2.子范围
- 1)List.subList可将任何操作应用于子范围(同步更新整个列表)
- 2)SortedSet和NavigableSet,SortedMap和NavigableMap
SortedSet.subSet(from, to) 返回的是半闭区间[)
SortedSet.headSet(to)
SortedSet.tailSet(from)
NavigableSet.subSet headSet tailSet可控制边界是否包含
SortedMap.subMap(from, to) 返回的是半闭区间[)
SortedMap.headMap(to)
SortedMap.tailMap(from)
NavigableMap.subMap headMap tailMap可控制边界是否包含
3.不可修改的视图
不可修改视图对修改操作全部抛出异常,只能对其进行访问
Collections.unmodifiableCollection 其equals使用的Object
如下使用底层的equals:
Collections.unmodifiableList
Collections.unmodifiableSet
Collections.unmodifiableMap
以Collections.unmodifiableList为例:
public static <T> List<T> unmodifiableList(List<? extends T> list) {
return (list instanceof RandomAccess ?
new UnmodifiableRandomAccessList<>(list) :
new UnmodifiableList<>(list));
}
static class UnmodifiableList<E> extends UnmodifiableCollection<E>
implements List<E> {
private static final long serialVersionUID = -283967356065247728L;
final List<? extends E> list;
UnmodifiableList(List<? extends E> list) {
super(list);
this.list = list;
}
public boolean equals(Object o) {return o == this || list.equals(o);}
public int hashCode() {return list.hashCode();}
public E get(int index) {return list.get(index);}
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 int indexOf(Object o) {return list.indexOf(o);}
public int lastIndexOf(Object o) {return list.lastIndexOf(o);}
public boolean addAll(int index, Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
4.同步视图
方法外面都包围了synchronized(mutex):
Collections.synchronizedCollection
Collections.synchronizedList
Collections.synchronizedSet
Collections.synchronizedMap
以Collections.synchronizedList为例:
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
}
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;
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 boolean equals(Object o) {
if (this == o)
return true;
synchronized (mutex) {return list.equals(o);}
}
public int hashCode() {
synchronized (mutex) {return list.hashCode();}
}
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);}
}
5.受查视图
用来对泛型类型发生问题提供调试支持,如果加入的类型不匹配,会抛出ClassCastException异常。
Collections.checkedCollection()
Collections.checkedList
Collections.checkedSet
Collections.checkedMap
以Collections.checkedList为例
public static <E> List<E> checkedList(List<E> list, Class<E> type) {
return (list instanceof RandomAccess ?
new CheckedRandomAccessList<>(list, type) :
new CheckedList<>(list, type));
}
static class CheckedList<E>
extends CheckedCollection<E>
implements List<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 boolean equals(Object o) { return o == this || list.equals(o); }
public int hashCode() { return list.hashCode(); }
public E get(int index) { return list.get(index); }
public E remove(int index) { return list.remove(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) {
return list.set(index, typeCheck(element));
}
public void add(int index, E element) {
list.add(index, typeCheck(element));
}
@SuppressWarnings("unchecked")
E typeCheck(Object o) {
if (o != null && !type.isInstance(o))
throw new ClassCastException(badElementMsg(o));
return (E) o;
}
6.集合框架本身的视图
Map有如下三个视图,这三个视图只能删除,不可添加:
-
Set<K> keySet()
Collection<V> values()
Set<Map.Entry<K, V>> entrySet()
如上图三个方法返回的KeySet Values EntrySet自身都没有add方法,该方法继承自AbstractCollection,抽象类中的add是抛出异常。
public boolean add(E e) {
throw new UnsupportedOperationException();
}
7.批操作
- Collection
containsAll
addAll
removeAll
retainAll
clear - List
addAll(i, elements)在指定位置批量插入
8.集合与数组之间的转换
- 数组 -> 集合 Arrays.asList方法
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
ArrayList重写了get和set,对于add和remove继承自AbstractList,这两个方法都是抛出异常:
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* <p>This implementation always throws an
* {@code UnsupportedOperationException}.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E remove(int index) {
throw new UnsupportedOperationException();
}
- 集合 -> 数组 Collection中两个方法
Object[] toArray();
<T> T[] toArray(T[] a);
对于第二种toArray,支持泛型,保存了类型信息。若a足够大,直接填入,剩余填null;否则,分配新数组,类型与a相同。容量一致时,性能最好。