首页 > 代码库 > Java Maps

Java Maps

HashMap

  • 是线程不安全的,主要对于写操作来说,两个以上线程同时写入Map会被互相覆盖。线程安全指的保证对同一个map的写入操作按照顺序进行,一次只能一个线程更改。比如向HashMap里put(key, value1)有可能key对应的是其他线程同时写入的value2

  • HashMap的遍历有两种常用的方法,那就是使用keyset及entryset来进行遍历,但两者的遍历速度是有差别的.

第一种:

  // 效率高,以后一定要使用此种方式!
Map map = new HashMap();   Iterator iter = map.entrySet().iterator();   while (iter.hasNext()) {    Map.Entry entry = (Map.Entry) iter.next();    Object key = entry.getKey();    Object val = entry.getValue();   }

第二种:

  // 效率低,以后尽量少使用!
Map map = new HashMap();   Iterator iter = map.keySet().iterator();   while (iter.hasNext()) {    Object key = iter.next();    Object val = map.get(key);   }
  • HashMap或者ArrayList边遍历边删除数据会报java.util.ConcurrentModificationException异常,需要用Iterator遍历删除。ConcurrentHashMap没有这种问题。

public void test() {  

    Map bb = new HashMap();  

    bb.put("1", "wj");  

    bb.put("2", "ry");  

    Iterator it = bb.keySet().iterator();  

    while(it.hasNext()) {  

        Object ele = it.next();  

        #bb.remove(ele);    //wrong

        it.remove(ele);    //right
    }  

    System.out.println("Success!");
}
  • 对于ArrayList,不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。

//Right

Iterator<String> it = a.iterator();  

while(it.hasNext()){      

       String temp =  it.next();

       if(删除元素的条件){

             it.remove();             

       }      

}

 

//Wrong

List<String> a = new ArrayList<String>();

a.add("1");      

a.add("2");      

for (String temp : a) {

     if("1".equals(temp)){  

           a.remove(temp);          

     }      

}  

ConcurrentHashMap

  • public V get(Object key)不涉及到锁,也就是说获得对象时没有使用锁,保证读到最新的值

  • put、remove方法要使用锁,但并不一定有锁争用,原因在于ConcurrentHashMap将缓存的变量分到多个Segment,每个Segment上有一个锁,只要多个线程访问的不是一个Segment就没有锁争用,就没有堵塞,各线程用各自的锁,ConcurrentHashMap缺省情况下生成16个Segment,也就是允许16个线程并发的更新而尽量没有锁争用;

  • Iterator对象的使用,不一定是和其它更新线程同步,获得的对象可能是更新前的对象,ConcurrentHashMap允许一边更新、一边遍历,也就是说在Iterator对象遍历的时候,ConcurrentHashMap也可以进行remove,put操作,且遍历的数据会随着remove,put操作产出变化,所以希望遍历到当前全部数据的话,要么以ConcurrentHashMap变量为锁进行同步(synchronized该变量),要么使用CopiedIterator包装iterator,使其拷贝当前集合的全部数据,但是这样生成的iterator不可以进行remove操作。

  • ConcurrentHashMap is much quicker than SynchronizedHashMap. ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

  • 对ConcurrentHashMap边遍历边删除或者增加操作不会产生异常(可以不用迭代方式删除元素),因为其内部已经做了维护,遍历的时候都能获得最新的值。即便是多个线程一起删除、添加元素也没问题。

  • ConcurrentHashMap或者说所有的Map都不保证非原子性的操作,比如判断contains后再get的值可能已经改变,需要对整个Map加锁

  • You should use ConcurrentHashMap when you need very high concurrency in your project.

  • It is thread safe without synchronizing the whole map.

  • Reads can happen very fast while write is done with a lock.

  • There is no locking at the object level.

  • The locking is at a much finer granularity at a hashmap bucket level.

  • ConcurrentHashMap doesn’t throw a ConcurrentModificationException if one thread tries to modify it while another is iterating over it.

  • ConcurrentHashMap uses multitude of locks

HashTable

  • 线程安全,但是对整个Map上锁,读和写都需要同步,在高竞争环境下效率很低,有Scalability 的问题

  • Note that this implementation is not synchronized. If multiple threads access a hashmap concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map. If no such object exists, the map should be "wrapped" using the Collections.synchronizedMap method. This is best done at creation time, to prevent accidental unsynchronized access to the map

SynchronizedHashMap

  • Synchronization at Object level.

  • Every read/write operation needs to acquire lock.

  • Locking the entire collection is a performance overhead.

  • This essentially gives access to only one thread to the entire map & blocks all the other threads.

  • It may cause contention.

  • SynchronizedHashMap returns Iterator, which fails-fast on concurrent modification.


集合类

Key

Value

Super

说明

Hashtable

不允许为 null

不允许为 null

Dictionary

线程安全

ConcurrentHashMap

不允许为 null

不允许为 null

AbstractMap

线程局部安全

TreeMap

不允许为 null

允许为 null

AbstractMap

线程不安全

HashMap

允许为 null

允许为 null

AbstractMap

线程不安全



Java Maps