首页 > 代码库 > android开发之-数据存储Map、HashMap、Hashtable、concurenthashmap区别

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="http://www.mamicode.com/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值、遍历顺序固定、线程不安全
 
 
本文有理解不对的地方希望大家指正