??視圖(Views),簡(jiǎn)單的說(shuō)就是具有限制的集合對(duì)象。
??通過(guò)使用視圖(Views)可以獲得其他的實(shí)現(xiàn)了Collection接口和Map接口的對(duì)象。映射類的keySet方法就是一個(gè)這樣的示例。keySet方法返回一個(gè)實(shí)現(xiàn)Set接口的類對(duì)象,這個(gè)類的方法可以對(duì)原映射進(jìn)行操作。
??視圖技術(shù)在集合框架中有許多非常有用的應(yīng)用。
1.輕量級(jí)集合包裝器
??Arrays類的靜態(tài)方法asList將返回一個(gè)包裝了普通Java數(shù)組的List包裝器。
Card[] cardDeck = new Card[52];
...
List<Card> cardList = Arrays.asList(cardDeck);
??返回的對(duì)象不是ArrayList。它是一個(gè)視圖對(duì)象,帶有訪問(wèn)底層數(shù)組的get和set方法。改變數(shù)組大小的所有方法都會(huì)拋出一個(gè)異常。
2.子范圍
??可以為很多集合建立子范圍視圖。例如一個(gè)列表staff,想從中取出第10個(gè)~第19個(gè)元素??梢?strong>使用subList方法來(lái)獲得一個(gè)列表的子范圍視圖。
List group = staff.subList(10, 20);
??對(duì)于有序集和映射,可以使用排序順序而不是元素位置建立子范圍。下面這些方法將返回大于等于from且小于to的所有元素子集。
SortedSet<E> subSet(E from, E to)
SortedSet<E> headSet(E to)
SortedSet<E> tailSet(E from)
??返回映射視圖,該映射包含鍵落在指定范圍內(nèi)的所有元素。
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還有幾個(gè)方法,用于產(chǎn)生集合的不可修改視圖(unmodifiable views)。這些視圖對(duì)現(xiàn)有集合增加了一個(gè)運(yùn)行時(shí)的檢查。如果發(fā)現(xiàn)試圖對(duì)集合進(jìn)行修改,就拋出一個(gè)異常,同時(shí)這個(gè)集合將保持未修改的狀態(tài)。
??可以使用下面8中方法獲得不可修改視圖:
//每個(gè)方法定義于一個(gè)接口
Collections.unmodifiableCollection
Collections.unmodifiableList
Collections.unmodifiableSet
Collections.unmodifiableSortedSet
Collections.unmodifiableNavigableSet
Collections.unmodifiableMap
Collections.unmodifiableSortedMap
Collections.unmodifiableNavigableMap
??例如,想要查看某部分代碼,但又不觸及某個(gè)集合的內(nèi)容,就可以進(jìn)行下列操作:
List<String> staff = new LiskedList<>();
...
lookAt(Collections.unmodifiableList(staff));
??Collections.unmodifiableList方法將返回一個(gè)實(shí)現(xiàn)List接口的類對(duì)象。其訪問(wèn)器方法將從staff集合中獲取值。當(dāng)然,lookAt方法可以調(diào)用List接口中的所有方法,而不只是訪問(wèn)器。但是所有的更改器方法已經(jīng)被重新定義為異常,而不是將調(diào)用傳遞給底層集合。
??由于視圖只是包裝了接口,而不是實(shí)際的集合對(duì)象,所以只能訪問(wèn)接口中定義的方法。例如,LinkedList類中有一些非常方便的方法,addFirst和addLast,他們都不是List接口的方法,不能通過(guò)不可修改視圖進(jìn)行訪問(wèn)。
4.同步視圖
??如果由多個(gè)線程訪問(wèn)集合,就必須確保集合不會(huì)被意外地破壞。類庫(kù)的設(shè)計(jì)者使用視圖機(jī)制來(lái)確保常規(guī)集合的線程安全,而不是實(shí)現(xiàn)線程安全的集合。例如,Collections類的靜態(tài)synchronizedMap方法可以將任何一個(gè)映射表轉(zhuǎn)換成具有同步訪問(wèn)方法的Map:
Map<String, Employee> map = Collections.synchronizedMap(new HashMap<String, Employee>());
??現(xiàn)在,就可以由多線程訪問(wèn)map對(duì)象了。像get和put這類方法都是同步操作的,即在另一個(gè)線程調(diào)用另一個(gè)方法之前,剛才的方法調(diào)用必須徹底完成。
5.受查視圖
??“受查”視圖用來(lái)對(duì)泛型類型發(fā)生問(wèn)題時(shí)提供調(diào)試支持。
ArrayList<String> strings = new ArrayList<>();
ArrayList rawList = strings;
rawList.add(new Date());//Error
??這個(gè)錯(cuò)誤的add命令在運(yùn)行時(shí)檢測(cè)不到。相反,只有在稍后的另一部分代碼中調(diào)用get方法,并將結(jié)果轉(zhuǎn)化為String時(shí),才會(huì)拋出異常。
??受查視圖可以探測(cè)到這類問(wèn)題。
List<String> safeStrings = Collections.checkedList(strings, String.class);
??視圖的add方法將檢測(cè)插入的對(duì)象是否屬于給定的類。