1. 程式人生 > >java集合---檢視與包裝器

java集合---檢視與包裝器

檢視—-通過使用檢視可以獲得其他實現了Collection與Map介面的物件。對映類的keySet就是這樣一個例項。初看起來,好像這個方法建立了一個新集,並將對映中的所有鍵都填進去,然後返回這個集。但是,事實並非如此。取而代之的是:keySet方法返回一個實現了Set介面的類物件,這個類的方法對原對映進行操作。這種集合就是檢視。

輕量級集合包裝器

Arrays類的靜態方法asList將返回一個包裝了普通java陣列的List包裝器,這個方法可以將陣列傳遞給一個期望得到的列表或集合引數中:

package view;

import java.util.Arrays;
import java.util
.Collections; import java.util.List; public class Testview01 { public static void main(String[] args) { String[] str = new String[10]; //這裡返回的物件不是一個ArrayList。它是一個檢視物件,帶有訪問底層陣列的get和set方法 List<String> list = Arrays.asList(str); list.set(2, "aaa"); System.out
.println(list.get(2)); //改變陣列大小的所有方法,例如add、remove方法等,都會丟擲Unsupported OperationException異常 //list.add("aaa"); System.out.println(list.size()); System.out.println("----------我是分割線----------"); //asList可以接受可變數目的引數 List<String> names = Arrays.asList("aa", "bb"
, "cc"); System.out.println(names); //names.add("aaaaaa");同樣會報錯,原因同上 System.out.println(names.size()); System.out.println("----------我是分割線----------"); List<String> set = Collections.nCopies(100, "default"); //實際上在這裡只進行了一次賦值操作,詳見jdk System.out.println(set.get(0) == set.get(10)); } }

這裡寫圖片描述
這是關於Collections.nCopies()方法的jdk原始碼截圖,這裡充分說明了它只進行了一次賦值。

區分Collections類和Collection介面

Collections類包含了很多實用的方法,這些方法的引數和返回值都是集合;不要與Collection介面混淆。

//這個方法將返回一個檢視物件。這個物件實現了Set介面,返回的物件實現了一個不可修改的單元素集,
        //而不需要付出建立資料結構的開銷
        Set singleton = Collections.singleton(names);
        for(Object sets : singleton) {
            System.out.println(sets);

子範圍

package view;

import java.util.Arrays;
import java.util.List;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

public class TestView02 {
    public static void main(String[] args) {
        String[] str = new String[]{"aa", "dd", "ff", "cc", "qq", "bb"};
        List<String> list = Arrays.asList(str);
        System.out.println(list);
        List group = list.subList(2, 5);
        System.out.println(group);
        System.out.println("----------我是分割線----------");
        SortedSet<String> set = new TreeSet<String>(list);
        SortedSet<String> subset = set.subSet("aa", "dd");//大於aa小於dd不包含dd
        System.out.println(subset);
        subset.clear();//刪除選中的項,並且直接反應在原對映中
        System.out.println(set);

        System.out.println("----------我是分割線----------");
        SortedMap<Integer, String> map = new TreeMap<Integer, String>();
        map.put(1, "ff");
        map.put(2, "aa");
        map.put(3, "gg");
        map.put(4, "ee");
        map.put(5, "cc");
        System.out.println(map);
        SortedMap<Integer, String> submap = map.subMap(2, 4);
        System.out.println(submap);
        submap.clear();
        System.out.println(map);
    }
}

不可修改檢視

Collections 還有幾個方法, 用於產生集合的不可修改檢視。 這些檢視對現有集合增加了一個執行時的檢查。 如果發現試圖對集合進行修改, 就丟擲一個異常, 同時這個集合將保持未修改狀態;
(再次提醒:注意區分 Collection 和 Collections)

可以使用下列8種方法獲得不可修改檢視:

Collections.unmodifiableCollection
Collections.unmodifiableList
Collections.unmodifiableSet
Collections.unmodifiableSortedSet
Collections.unmodifiableMap
Collections.unmodifiableSortedMap
Collections.unmodifiableNavigableSet
Collections.unmodifianleNavigableMap
每個方法都定義於一個介面。如, Collections.unmodifiableList 與 ArrayList、LinkedList 或者任何實現了 List介面的其他類一起協同工作;

package view;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class TestView03 {
    public static void main(String[] args) {
        List<String> list = Collections.nCopies(5, "default");
        List view = Collections.unmodifiableList(list);//該方法獲取不可修改的檢視
        System.out.println(view.get(0));
        view.add("aaa");//報錯,獲取的是不可修改檢視
        System.out.println("----------我是分割線----------");
        List<String> staff = new LinkedList<String>();
        lookAt(Collections.unmodifiableList(staff));
    }
}

Collections.unmodifiableList 方法返回一個實現List介面的類物件。當然,lookAt方法 可以呼叫 List 介面中的所有方法, 而不只是訪問器。但是所有的更改器方法,已經被重新定義為 丟擲一個 UnsuportedOperationException 異常,而不是 將呼叫傳遞給底層集合;
注意:
不可修改檢視並不是聚合本身不可修改,只是無法通過其投影出來的檢視修改原集合。仍然可以實用集合的原始引用修改原集合。
由於檢視只是包裝了介面而不是實際的集合物件,所以只能訪問介面中定義的方法。例如,LinkedList類有一些常用的方法,addFirst和addLast,他們都不是List介面方法,不能通過不可修改檢視訪問。

同步檢視

  如果由多個執行緒訪問集合,就必須確保集不會被意外的破壞。類庫設計者使用檢視機制來確保常規集合的執行緒安全,而不是實現執行緒安全的集合。例如,Collections類的靜態synchronizedMap可以將任何一個對映錶轉換成具有同步訪問方法的Map:
Map<String, Employee> map = Collections.synchronizedMap(new HashMap<String, Employee>())

受查檢視

package view;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

public class TestView04 {
    public static void main(String[] args) {
        ArrayList<String> str = new ArrayList<String>();
        ArrayList string = str;
        string.add(new Date());//到這裡並沒有發現新增的型別不符
        Date date = (Date)string.get(0);
        System.out.println(date);

        /*String s = (String) string.get(0);//這裡檢測到型別不匹配
        System.out.println(s);*/
        System.out.println("----------我是分割線----------");
        ArrayList<String> str2 = new ArrayList<String>();
        List<String>  safe = Collections.checkedList(str2, String.class); 
        List string02 = safe;
        string02.add(new Date());//編譯器沒有檢測到這裡的add異常
        System.out.println("ok");
    }
}