视图(Views),简单的说就是具有限制的集合对象。
通过使用视图(Views)可以获得其他的实现了Collection接口和Map接口的对象。映射类的keySet方法就是一个这样的示例。keySet方法返回一个实现Set接口的类对象,这个类的方法可以对原映射进行操作。
视图技术在集合框架中有许多非常有用的应用。
1.轻量级集合包装器
Arrays类的静态方法asList将返回一个包装了普通Java数组的List包装器。
Card[] cardDeck = new Card[52];
...
List<Card> cardList = Arrays.asList(cardDeck);
返回的对象不是ArrayList。它是一个视图对象,带有访问底层数组的get和set方法。改变数组大小的所有方法都会抛出一个异常。
2.子范围
可以为很多集合建立子范围视图。例如一个列表staff,想从中取出第10个~第19个元素。可以使用subList方法来获得一个列表的子范围视图。
List group = staff.subList(10, 20);
对于有序集和映射,可以使用排序顺序而不是元素位置建立子范围。下面这些方法将返回大于等于from且小于to的所有元素子集。
SortedSet<E> subSet(E from, E to)
SortedSet<E> headSet(E to)
SortedSet<E> tailSet(E from)
返回映射视图,该映射包含键落在指定范围内的所有元素。
SortedMap<K, V> subMap(K from, K to)
SortedMap<K, V> headMap(K to)
SortedMap<K, V> tailMap(K from)
Java SE 6引入的NavigableSet接口赋予子范围操作更多的控制能力。
3.不可修改的视图
Collections还有几个方法,用于产生集合的不可修改视图(unmodifiable views)。这些视图对现有集合增加了一个运行时的检查。如果发现试图对集合进行修改,就抛出一个异常,同时这个集合将保持未修改的状态。
可以使用下面8中方法获得不可修改视图:
//每个方法定义于一个接口
Collections.unmodifiableCollection
Collections.unmodifiableList
Collections.unmodifiableSet
Collections.unmodifiableSortedSet
Collections.unmodifiableNavigableSet
Collections.unmodifiableMap
Collections.unmodifiableSortedMap
Collections.unmodifiableNavigableMap
例如,想要查看某部分代码,但又不触及某个集合的内容,就可以进行下列操作:
List<String> staff = new LiskedList<>();
...
lookAt(Collections.unmodifiableList(staff));
Collections.unmodifiableList方法将返回一个实现List接口的类对象。其访问器方法将从staff集合中获取值。当然,lookAt方法可以调用List接口中的所有方法,而不只是访问器。但是所有的更改器方法已经被重新定义为异常,而不是将调用传递给底层集合。
由于视图只是包装了接口,而不是实际的集合对象,所以只能访问接口中定义的方法。例如,LinkedList类中有一些非常方便的方法,addFirst和addLast,他们都不是List接口的方法,不能通过不可修改视图进行访问。
4.同步视图
如果由多个线程访问集合,就必须确保集合不会被意外地破坏。类库的设计者使用视图机制来确保常规集合的线程安全,而不是实现线程安全的集合。例如,Collections类的静态synchronizedMap方法可以将任何一个映射表转换成具有同步访问方法的Map:
Map<String, Employee> map = Collections.synchronizedMap(new HashMap<String, Employee>());
现在,就可以由多线程访问map对象了。像get和put这类方法都是同步操作的,即在另一个线程调用另一个方法之前,刚才的方法调用必须彻底完成。
5.受查视图
“受查”视图用来对泛型类型发生问题时提供调试支持。
ArrayList<String> strings = new ArrayList<>();
ArrayList rawList = strings;
rawList.add(new Date());//Error
这个错误的add命令在运行时检测不到。相反,只有在稍后的另一部分代码中调用get方法,并将结果转化为String时,才会抛出异常。
受查视图可以探测到这类问题。
List<String> safeStrings = Collections.checkedList(strings, String.class);
视图的add方法将检测插入的对象是否属于给定的类。
网友评论