Java之Collections工具類方法使用以及源碼分析(一)__Java

來源:互聯網
上載者:User

概念區分: java.util.Collection和java.util.Collections區別:

1、 java.util.Collection 是一個集合介面(集合類的一個頂級介面)。它提供了對集合對象進行基本操作的通用介面方法。Collection介面在Java 類庫中有很多具體的實現。Collection介面的意義是為各種具體的集合提供了最大化的統一操作方式,其直接繼承介面有List與Set。

2、java.util.Collections 是一個封裝類(工具類/協助類)。它包含有各種有關集合操作的靜態多態方法。此類不能執行個體化,就像一個工具類,用於對集合中元素進行排序、搜尋以及安全執行緒等各種操作,服務於Java的Collection架構。


既然Collections是服務於Collection架構的,那麼我們就嘗試學習使用:

方法1:

java.util.Collections.unmodifiableCollection(Collection<? extends Double>): 返回指定 collection 的不可修改視圖。

package com.daxin.collections;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;public class Main1 {public static void main(String[] args) {Collection<Double> list = new ArrayList<Double>();double array[] = { 75, 52, 99, 102, 78,23 };System.out.println("list.hashCode()1 "+list.hashCode());for (int i = 0; i < array.length; i++) {list.add(array[i]);}System.out.println("list.hashCode()2 "+list.hashCode());//返回不可以修改視圖Collection<Double> unmodifiableCollection = Collections.unmodifiableCollection(list);unmodifiableCollection.add(1.2);//拋異常for (Double d : unmodifiableCollection) {System.out.println(d);}}}

當我們對返回的不可修改視圖進行調用unmodifiableCollection.add(1.2)修改時候,會拋出異常:

Exception in thread "main" java.lang.UnsupportedOperationExceptionat java.util.Collections$UnmodifiableCollection.add(Collections.java:1075)at com.daxin.collections.Main1.main(Main1.java:24)

那究竟是如何?不可以修改的呢? 答案:使用的代理模式,具體過程看源碼如下:

返回的不可修改檢視類型為:java.util.Collections.UnmodifiableCollection<E>,是Collections的一個靜態內部類,而unmodifiableCollection方法實現如下:

    public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) {        return new UnmodifiableCollection<>(c);    }

其中c是 UnmodifiableCollection類中的一個成員:

 final Collection<? extends E> c;
此處是不是會有疑問。c是final的,但是內部成員應該可以修改。為什麼。

拓展補充:首先ArrayList的實現底層就是使用的數組:

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable{private static final long serialVersionUID = 8683452581122892189L;private static final int DEFAULT_CAPACITY = 10;private static final Object[] EMPTY_ELEMENTDATA = {};private transient Object[] elementData;...等}

所以對於 final Collection<? extends E> c中finalc為什麼不可修修改感覺疑問呢。其實此處使用代理模式是對add方法進行了增強,看一下add方法就知道了:

        public boolean add(E e) {            throw new UnsupportedOperationException();        }

答案自然見分曉了吧。

但是需要注意的是,如果我們自己在代碼中修改了原始的那個list,那麼unmodifiableCollection也會被修改,這裡的視圖類似資料庫的視圖。


接下來看看方法:

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)

返回一個同步的Map。返回由指定映射支援的同步(安全執行緒的)映射。為了保證按順序訪問,必須通過返回的映射完成所有對底層實現映射的訪問。

首先看一下非安全執行緒的HashMap:

package com.daxin.collections;import java.util.HashMap;import java.util.Map;class Service {private Map map = null;public Service(Map map) {super();this.map = map;}public Map getMap() {return map;}public void setMap(Map map) {this.map = map;} }class ThreadA extends Thread {private Service service;public ThreadA(Service service) {super();this.service = service;}@Overridepublic void run() {for (int i = 1; i <= 5; i++) {service.getMap().put(i + "", i + "");}}}class ThreadB extends Thread {private Service service;public ThreadB(Service service) {super();this.service = service;}@Overridepublic void run() {for (int i = 1; i <= 5; i++) {service.getMap().put(i + "", i + "AAA");}}}public class Main2 {public static void main(String[] args) throws Exception {Map map=new HashMap<String,String>();Service service = new Service(map);ThreadA a = new ThreadA(service);ThreadB b = new ThreadB(service);a.start();b.start();a.join();b.join();System.out.println(service.getMap());// 輸出{3=3AAA, 2=2AAA, 1=1AAA, 5=5AAA, 4=4AAA} 或者{3=3AAA, 2=2AAA, 1=1,// 5=5AAA, 4=4AAA} 多次運行結果不一致,兩個線程交替執行導致結果多次輸出不一致。出現了安全執行緒問題//安全執行緒的請看Main3源碼}}


改進版,安全執行緒版本:


package com.daxin.collections;import java.util.Collections;import java.util.HashMap;import java.util.Map;public class Main3 {public static void main(String[] args) throws Exception {Map map=Collections.synchronizedMap(new HashMap<String,String>());Service service = new Service(map);ThreadA a = new ThreadA(service);ThreadB b = new ThreadB(service);a.start();b.start();a.join();b.join();System.out.println(service.getMap());//輸出:{3=3AAA, 2=2AAA, 1=1AAA, 5=5AAA, 4=4AAA}或者{3=3, 2=2, 1=1, 5=5, 4=4} 兩種結果了,這就主要看//誰先得到鎖了誰後得到鎖了,輸出的是最後得到鎖的結果。//不會兩個線程交替執行了}}

接下來看看synchronizedMap的方法源碼:

    public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {        return new SynchronizedMap<>(m);    }

再看看SynchronizedMap構造方法(SynchronizedMap是Collections的一個靜態內部類):

private static class SynchronizedMap<K, V> implements Map<K, V>, Serializable {private static final long serialVersionUID = 1978198479659022715L;private final Map<K, V> m; // Backing Mapfinal Object mutex; // Object on which to synchronize,同步加鎖對象SynchronizedMap(Map<K,V> m) {    if (m==null)        throw new NullPointerException();    this.m = m;    mutex = this;//將mutex設定為當前對象,還有其他建構函式自行查看}...等}

再看看SynchronizedMap的put等常用方法源碼:

  public V put(K key, V value) {            synchronized (mutex) {return m.put(key, value);}        }        public V remove(Object key) {            synchronized (mutex) {return m.remove(key);}        }        public void putAll(Map<? extends K, ? extends V> map) {            synchronized (mutex) {m.putAll(map);}        }
每一次對SynchronizedMap進行操作其實都是對mutex對象加鎖進行的,使用的是synchronized代碼塊實現。


在看看java.util.Collections.synchronizedSet(Set<String>)方法,原理類似:

建立一個SynchronizedSet返回(SynchronizedSet繼承SynchronizedCollection類,SynchronizedCollection中實現對成員mutex的成員進行代碼塊同步)。

方法java.util.Collections.synchronizedList(List<String>)實現原理也是如上。









聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.