java集合——视图与包装器
【0】README
0.1) 本文描述轉自 core java volume 1, 源代碼為原創,旨在理解 java集合——視圖與包裝器 的相關知識;
0.2) for full source code , please visit https://github.com/pacosonTang/core-java-volume/blob/master/chapter13/ViewAndWrapper.java
1.1)通過使用視圖可以獲得其他的實現了集合接口和映射表接口的對象;
- 1.1.1)視圖定義:映射表類的keySet方法就是這樣一個荔枝;keySet 方法返回一個實現了Set接口的類對象, 這個類的方法對原映射表進行操作, 這種集合稱為視圖;
1.2)集合框架中的遺留類圖概覽
1.3)輕量級集包裝器
- 1.3.1)Arrays類的靜態方法asList 將返回一個包裝了普通 java 數組的List 包裝器。 這個方法可以將數組傳遞給一個期望得到列表或集合變元的方法, 例如:
對以上代碼的分析(Analysis):
- A1)返回的對象不是 ArrayList。 它是一個視圖對象, 帶有訪問底層數組的get和set方法;而改變該數組大小的所有方法(與迭代器相關的add 和 remove方法) 都會拋出一個UnsupportedOperationException 異常;
- A2)asList方法: 它已經被聲明為一個具有可變參數的方法, 除了可以傳遞一個數組外, 還可以將各個元素直接傳遞給這個方法:
- A3)以上這個方法調用 Collections.nCopies(n , anObject) : 將返回一個實現了 List接口的不可修改對象, 并給人一種包含n個元素, 每個元素都是 Object的 錯覺;
- 1.3.2)看個荔枝:(干貨——創建了 100個 DEFAULT, 由于字符串對象只存儲了一次, 所以付出的存儲代價很小, 這是視圖技術的一種巧妙的應用)
干貨問題:(如何區分 Collection 和 Collections)
Anotation) Collections 類包含很多實用方法, 這些方法的參數和返回值都是集合。 不要將 Collection接口 和 Collections 包裝類 混淆起來了;
1.3.3)調用以下代碼: Collections.singleton(anObject); 則返回一個視圖對象。 這個對象實現了Set 接口。 返回的對象實現了一個不可修改的單元素集, 而不需要付出建立數據結構的 開銷。 singletonList 和 singletonMap 方法類似;
1.4) 子范圍
1.4.1)可以為很多集合建立子范圍視圖;
如, List g2 = staff.subList(10,20); 從列表staff 中取出 第10個~第19個元素;(第一個 索引包含在內,第二個索引不包含在內)- 1.4.2)可以將任何操作應用到子范圍, 并且能夠自動地反應整個列表的情況;
如, g2.clear(); 現在, 元素自動地從 staff 列表中清除了,并且g2 為空; 1.4.3)對于有序集合映射表, 可以使用 排序順序而不是元素位置建立子范圍。
1.4.3.1)SortedSet 接口說明了3個方法:
- 以上方法將返回 大于等于from 小于to的所有元素子集;
- 1.4.3.2)有序映射表有類似方法:
- 返回映射表視圖, 該映射表包含鍵落在指定范圍內的所有元素;
- 1.4.4) java SE6 引入的 NavigableSet 接口 賦予子范圍操作更多 的控制能力。 可以指定是否包括邊界:
1.5)不可修改視圖
- Collections 還有幾個方法, 用于產生集合的不可修改視圖。 這些視圖對現有集合增加了一個運行時的檢查。 如果發現試圖對集合進行修改, 就拋出一個異常, 同時這個集合將保持未修改狀態;
(再次提醒:注意區分 Collection 和 Collections) - 1.5.1)可以使用下列6種方法獲得不可修改視圖:
每個方法都定義于一個接口。如, Collections.unmodifiableList 與 ArrayList、LinkedList 或者任何實現了 List接口的其他類一起協同工作;
1.5.1荔枝):
- Collections.unmodifiableList 方法返回一個實現List接口的類對象。當然,lookAt方法 可以調用 List 接口中的所有方法, 而不只是訪問器。但是所有的更改器方法,已經被重新定義為 拋出一個 UnsuportedOperationException 異常,而不是 將調用傳遞給底層集合;
- 1.5.2)不可修改視圖并不是 集合本身不可修改 (干貨——只是無法通過其投影出的視圖修改原始集合)。 仍然可以通過集合的原始引用對集合進行修改。并且仍然可以讓集合的元素調用更改方法;
- 1.5.3)由于視圖只是包裝了 接口而不是 實際的集合對象, 所以只能訪問 接口中定義的方法; 如, LinkedList 類有一些非常方便的方法, addFirst 和 addLast , 它們都不是 List接口的方法,不能通過修改視圖進行訪問;
Warning)
- W1) unmodifiableCollection 方法將返回一個集合, 它的equals 方法不調用底層集合的equals 方法; 相反,它繼承了 Object 類的 equals 方法, 該方法只是檢測兩個對象是否是同一個對象;
- W2)如果將 集 或 列表轉換成集合, 就再也無法檢測其內容是否相同了, 視圖就是以這種方式運行的, 因為內容是否相等的檢測在分層結構的這一層上沒有定義妥當;
- W3)視圖將以同樣的方式處理 hashCode 方法;
1.6)同步視圖
- 1.6.1)如果由多個線程訪問集合,就必須確保集不會被意外破壞, 類庫的設計者使用視圖及直接來確保常規集合的線程安全。
- 1.6.2)例如, Collections 類的 靜態 synchronizedMap 方法將任何一個映射表轉換成具有同步訪問方法的 Map:
1.7)檢查視圖
- 1.7.1)出現的問題:
這個錯誤的 add 命令在運行時檢測不到。 相反,只有在 調用 get方法, 并將其 轉換為 String 時,這個類才會拋出一個異常;
1.7.2)解決方法:檢查視圖可以探測到這類問題。下面定義了一個安全列表:
List safeString = Collections.checkedList(strings, String.class);
視圖的add 方法將檢測 插入的對象是否屬于給定的類。 如果不屬于給定的類, 就立即拋出一個 ClassCastException。 這樣做的好處是錯誤可以在正確的位置得以報告:
Warning)
- W1)被檢測視圖受限于 虛擬機可以運行的運行時檢查。例如, 對于ArrayList
總結
以上是生活随笔為你收集整理的java集合——视图与包装器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java集合——集合框架
- 下一篇: java集合——集合与数组间的转换+算法