android開發之-數據存儲Map、HashMap、Hashtable、concurenthashmap區別


選擇一個map進行軟件基礎數據初始化操作,要求第一次初始化后,不修改數據,可能會出現靜態類被回收,然后在進行初始化操作?

1.Map :接口
/**
 * A {@code Map} is a data structure consisting of a set of keys and values
 * in which each key is mapped to a single value. The class of the objects
 * used as keys is declared when the {@code Map} is declared, as is the
 * class of the corresponding values.
 * <p>
 * A {@code Map} provides helper methods to iterate through all of the
 * keys contained in it, as well as various methods to access and update
 * the key/value pairs.
 */

  一個map是由一組鍵和值組成的數據結構 ,其中每個鍵映射到一個單一的值。當Map被聲明后,values的值將被作為key 的關聯值被聲明

Map提供幫助方法來遍歷所有它的包含鍵值,以及各種方法來訪問和更新鍵/值對。
ps:Map提供key、values形式的聲明,public interface Map<K,V>{}, map是一個接口,不能直接使用。

2.hashMap
/**
 * HashMap is an implementation of {@link Map}. All optional operations are supported.
 *
 * <p>All elements are permitted as keys or values, including null.
 *
 * <p>Note that the iteration order for HashMap is non-deterministic. If you want
 * deterministic iteration, use {@link LinkedHashMap}.
 *
 * <p>Note: the implementation of {@code HashMap} is not synchronized.
 * If one thread of several threads accessing an instance modifies the map
 * structurally, access to the map needs to be synchronized. A structural
 * modification is an operation that adds or removes an entry. Changes in
 * the value of an entry are not structural changes.
 *
 * <p>The {@code Iterator} created by calling the {@code iterator} method
 * may throw a {@code ConcurrentModificationException} if the map is structurally
 * changed while an iterator is used to iterate over the elements. Only the
 * {@code remove} method that is provided by the iterator allows for removal of
 * elements during iteration. It is not possible to guarantee that this
 * mechanism works in all cases of unsynchronized concurrent modification. It
 * should only be used for debugging purposes.
 *
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 */

  HashMap繼承了map,實現了map的所有方法。key和value允許使用全部的元素,包括null

注意 遍歷hashMap是隨機的,如果你想定義遍歷順序,請使用LinkedHashMap。
注意: HashMap實現是不同步的。如果多個線程的一個線程訪問一個實例map,修改了該map結構,使用的map需要同步。  
結構上的修改是指添加或刪除一個節點的操作。改變一個map的值不是結構上的變化。
通過Iterator創建並遍歷hashMap時,如果使用iterator遍歷map的元素,map的結構被修改時,此時可能拋ConcurrentModificationException異常,就是結構不唯一異常,(通常是遍歷時節點被刪除或修改操作。)
只有通過迭代器提供的remove方法允許在迭代過程中移除元素。但 這是不可能保證該機制的作用於不同步的並發修改操作的所有情況。  
它應該只用於調試目的。
ps:HashMap准許key和values使用null,遍歷hashMap是唯一的,結構修改不同步。

3.hashtable
/**
 * Hashtable is a synchronized implementation of {@link Map}. All optional operations are supported.
 *
 * <p>Neither keys nor values can be null. (Use {@code HashMap} or {@code LinkedHashMap} if you
 * need null keys or values.)
 *
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 * @see HashMap
 */

  Hashtable 同步繼承map,支持map的全部操作。

無論是key還是value都不可以為null。(所以使用較少)可以使用hashMap或linkedhashMap來存儲key或者values的空值。

4.ConcurrentMap 接口
/**
 * A {@link java.util.Map} providing additional atomic
 * <tt>putIfAbsent</tt>, <tt>remove</tt>, and <tt>replace</tt> methods.
 *
 * <p>Memory consistency effects: As with other concurrent
 * collections, actions in a thread prior to placing an object into a
 * {@code ConcurrentMap} as a key or value
 * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
 * actions subsequent to the access or removal of that object from
 * the {@code ConcurrentMap} in another thread.
 *
 * @since 1.5
 * @author Doug Lea
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 */

  一個map的附加方法,提供putIfAbsent和remove(移除)、replace(替換)方法。

內存一致性: 由於存在其他並發集合, 在一個線程將對象放入一個ConcurrentMap作為一個鍵或值之前,會向訪問或關聯的ConcurrentMap在另一個線程中去除該對象的后續。
ps:ConcurrentMap 是線程安全的 ConcurrentMap的操作都是原子操,擴展了map。
-----------------------------------------------------------------------------------------------------------------------------
初次看到putIfAbsent,研究下,語意:如果不存在put
 
/**
     * If the specified key is not already associated
     * with a value, associate it with the given value.
     * This is equivalent to
     * <pre>
     * if (!map.containsKey(key))
     * return map.put(key, value);
     * else
     * return map.get(key);</pre>
     * except that the action is performed atomically.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with the specified key, or
     * <tt>null</tt> if there was no mapping for the key.
     * (A <tt>null</tt> return can also indicate that the map
     * previously associated <tt>null</tt> with the key,
     * if the implementation supports null values.)
     * @throws UnsupportedOperationException if the <tt>put</tt> operation
     * is not supported by this map
     * @throws ClassCastException if the class of the specified key or value
     * prevents it from being stored in this map
     * @throws NullPointerException if the specified key or value is null,
     * and this map does not permit null keys or values
     * @throws IllegalArgumentException if some property of the specified key
     * or value prevents it from being stored in this map
     *
     */
    V putIfAbsent(K key, V value);

這個意思簡單,直接看代碼:

 if (!map.containsKey(key))
     return map.put(key, value);
      else
      return map.get(key);

如果map不包含key那么就添加這個key、values否則返回這個key的values值。不允許key為null


5.Concurenthashmap
/**
 * A hash table supporting full concurrency of retrievals and
 * adjustable expected concurrency for updates. This class obeys the
 * same functional specification as {@link java.util.Hashtable}, and
 * includes versions of methods corresponding to each method of
 * <tt>Hashtable</tt>. However, even though all operations are
 * thread-safe, retrieval operations do <em>not</em> entail locking,
 * and there is <em>not</em> any support for locking the entire table
 * in a way that prevents all access. This class is fully
 * interoperable with <tt>Hashtable</tt> in programs that rely on its
 * thread safety but not on its synchronization details.
 *
 * <p> Retrieval operations (including <tt>get</tt>) generally do not
 * block, so may overlap with update operations (including
 * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
 * of the most recently <em>completed</em> update operations holding
 * upon their onset. For aggregate operations such as <tt>putAll</tt>
 * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
 * removal of only some entries. Similarly, Iterators and
 * Enumerations return elements reflecting the state of the hash table
 * at some point at or since the creation of the iterator/enumeration.
 * They do <em>not</em> throw {@link ConcurrentModificationException}.
 * However, iterators are designed to be used by only one thread at a time.
 *
 * <p> The allowed concurrency among update operations is guided by
 * the optional <tt>concurrencyLevel</tt> constructor argument
 * (default <tt>16</tt>), which is used as a hint for internal sizing. The
 * table is internally partitioned to try to permit the indicated
 * number of concurrent updates without contention. Because placement
 * in hash tables is essentially random, the actual concurrency will
 * vary. Ideally, you should choose a value to accommodate as many
 * threads as will ever concurrently modify the table. Using a
 * significantly higher value than you need can waste space and time,
 * and a significantly lower value can lead to thread contention. But
 * overestimates and underestimates within an order of magnitude do
 * not usually have much noticeable impact. A value of one is
 * appropriate when it is known that only one thread will modify and
 * all others will only read. Also, resizing this or any other kind of
 * hash table is a relatively slow operation, so, when possible, it is
 * a good idea to provide estimates of expected table sizes in
 * constructors.
 *
 * <p>This class and its views and iterators implement all of the
 * <em>optional</em> methods of the {@link Map} and {@link Iterator}
 * interfaces.
 *
 * <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
 * does <em>not</em> allow <tt>null</tt> to be used as a key or value.
 *
 * @since 1.5
 * @author Doug Lea
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 */

  一個哈希表,它支持檢索的完全並發和更新的所期望可調整並發。這個類遵循相同的功能規范的哈希表,並包括相應的哈希表的每個方法的方法版本。然而,即使所有操作都是線程安全的,檢索操作不涉及鎖定,並沒有鎖定整個表中,可以防止所有的接入方式的任何支持. 這個類是完全兼容的Hashtable中依賴於它的線程安全,但不能在其同步的細節計划。

檢索操作(包括get )通常不會阻塞,因此與更新操作(包括放和刪除)可能會重疊。檢索反映着在他們最近完成的更新操作的結果.
對於聚合操作,比如的putAll和清除全部,並發檢索可能反映插入或移除只有一些條目。同樣,迭代器和枚舉返回的元素將反映哈希表的狀態在某些時候或在創建以來的迭代器/枚舉。他們不拋出ConcurrentModificationException 。然而,迭代器被設計成用於通過僅一次一個線程。
更新操作中允許的並發由可選concurrencyLevel構造函數的參數(默認16 ) ,這是作為一個提示的內部尺寸為指導(將表分割成16份,分別進行鎖,提高效率)。該表是在內部分配來嘗試允許並發更新的指示的數目不沖突。因為放置在哈希表是隨機的,實際的並發性會有所不同。理想情況下,你應該選擇一個值,以容納盡可能多的線程數都不會同時修改該表。 使用顯著更高的價值比你的需要可以浪費的空間和時間,以及顯著較低的值可能導致線程爭用。但高估和一個量級內低估通常不會有太大明顯的影響。 一個值是在適當的時候它是已知的只有一個線程將修改和所有其他將只讀取。此外,調整大小或任何其他類型的哈希表是一個比較緩慢的操作,因此,如果可能的話,提供預期的表大小的構造函數的估計是一個好辦法。
這個類的查看和迭代器,繼承實現Map和Iterator接口的所有可選方法。
像哈希表,但不像HashMap中, 這個類不允許空值被用來作為一個鍵或值。
ps:Concurenthashmap是線程安全的,它默認將表分成16份,准許多個修改操作,實現了鎖分離,提高效率。 ConcurrentHashMap不接受 null key和null value。

6.linkedhashMap
/**
 * LinkedHashMap is an implementation of {@link Map} that guarantees iteration order.
 * All optional operations are supported.
 *
 * <p>All elements are permitted as keys or values, including null.
 *
 * <p>Entries are kept in a doubly-linked list. The iteration order is, by default, the
 * order in which keys were inserted. Reinserting an already-present key doesn't change the
 * order. If the three argument constructor is used, and {@code accessOrder} is specified as
 * {@code true}, the iteration will be in the order that entries were accessed.
 * The access order is affected by {@code put}, {@code get}, and {@code putAll} operations,
 * but not by operations on the collection views.
 *
 * <p>Note: the implementation of {@code LinkedHashMap} is not synchronized.
 * If one thread of several threads accessing an instance modifies the map
 * structurally, access to the map needs to be synchronized. For
 * insertion-ordered instances a structural modification is an operation that
 * removes or adds an entry. Access-ordered instances also are structurally
 * modified by {@code put}, {@code get}, and {@code putAll} since these methods
 * change the order of the entries. Changes in the value of an entry are not structural changes.
 *
 * <p>The {@code Iterator} created by calling the {@code iterator} method
 * may throw a {@code ConcurrentModificationException} if the map is structurally
 * changed while an iterator is used to iterate over the elements. Only the
 * {@code remove} method that is provided by the iterator allows for removal of
 * elements during iteration. It is not possible to guarantee that this
 * mechanism works in all cases of unsynchronized concurrent modification. It
 * should only be used for debugging purposes.
 */

  節點都保存在一個雙向鏈表。迭代順序是,默認情況下,順序鑰匙插入。重新插入一個已經存在鍵不改變順序。如果三個參數的構造函數被使用,並且accessOrder 被指定為true ,迭代將在該條目被訪問的順序。

接入順序是由put,get的影響,和putAll的操作,改變值的節點不改變順序。
注:LinkedHashMap的實現不是同步的。 如果訪問一個實例的多個線程中的一個線程修改了在結構上該映射,獲得了這個map的要被同步。為插入順序實例的結構上的修改是一個操作, 刪除或添加一個條目。訪問順序的實例也有結構上修正通過put , get和putAll,因為這些方法 更改項目的順序。改變一個項目的值不是結構上的變化。該Iterator調用Iterator方法創建可能拋出ConcurrentModificationException異常,如果映射為結構改變,而一個迭代器來遍歷元素。只有這是由該迭代器設置remove方法可以用於去除迭代過程中的元素。這工作機制不能保證不同步的並發修改的所有情況。它應僅用於調試目的。
允許使用null值、遍歷順序固定、線程不安全

結論:hashMap不行,不同步。
         hashtable不行,同步(謝謝指正)。
         Concurenthashmap可以,但值不能為null,安全,效率高
         linkedhashMap 不 可以,允許使用null值、遍歷順序固定、線程不安全
 
 
本文有理解不對的地方希望大家指正

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM