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


线程不安全

时间: 2024-12-14 05:51:40

Java Maps的相关文章

Top 10 Mistakes Java Developers Make(转)

文章列出了Java开发者最常犯的是个错误. 1.将数组转换为ArrayList 为了将数组转换为ArrayList,开发者经常会这样做: ? 1 List<String> list = Arrays.asList(arr); Arrays.asList()会返回一个ArrayList,但这个ArrayList是Arrays的私有静态类,不是java.util.ArrayList.java.util.Arrays.ArrayList有set(), get(), contains()方法,但没有任

Java开发者常犯的十个错误

翻译自:Top 10 Mistakes Java Developers Make 文章列出了Java开发者最常犯的是个错误. 1.将数组转换为ArrayList 为了将数组转换为ArrayList,开发者经常会这样做: List<String> list = Arrays.asList(arr); Arrays.asList()会返回一个ArrayList,但这个ArrayList是Arrays的私有静态类,不是java.util.ArrayList.java.util.Arrays.Arra

jackson快速入门

1. 背景 目前维护的产品使用jackson处理json,现整理一下jackson相关资料,希望对初次接触jackson的新手有所帮助.     jackson主页: http://jackson.codehaus.org/     jackson document: http://wiki.fasterxml.com/JacksonJavaDocs     JacksonInFiveMinutes: http://wiki.fasterxml.com/JacksonInFiveMinutes 

Jackson - Quickstart

JSON Three Ways Jackson offers three alternative methods (one with two variants) for processing JSON: Streaming API (aka "Incremental parsing/generation") reads and writes JSON content as discrete events. org.codehaus.jackson.JsonParser reads, o

MyBatis出错Result Maps collection does not contain value for java.lang.Integer

Servlet.service() for servlet [SpringMVC] in context with path [/eyou] threw exception [Request processing failed; nested exception is org.apache.ibatis.builder.IncompleteElementException: Could not find result map java.lang.Integer] with root causej

json:JSONObject包的具体使用(JSONObject-lib包是一个beans,collections,maps,java arrays和xml和JSON互相转换的包)

1.JSONObject介绍 JSONObject-lib包是一个beans,collections,maps,java arrays和xml和JSON互相转换的包. 2.下载jar包 http://xiazai.jb51.net/201707/yuanma/lib_jb51.rar 提供了除JSONObject的jar之外依赖的其他6个jar包,一共7个jar文件 说明:因为工作中项目用到的版本是1.1的对应jdk1.3的版本,故本篇博客是基于1.1版本介绍的. 对应此版本的javadoc下载

解决Caused by: java.lang.IllegalArgumentException: Result Maps collection does not contain value for com.geek.dao.ContentDao.Integer

mybatis报错:Caused by: java.lang.IllegalArgumentException: Result Maps collection does not contain value for com.geek.dao.ContentDao.Integer 出错原因:一个手误 <select id="selectAllFirstNavigationName" resultMap="firstNavigation"> SELECT fi

mybatis 异常Result Maps collection does not contain value for java.lang.String

Result Maps collection does not contain value for java.lang.String 以上是我报的错. 只要报Result Maps collection does not contain value for*****的错误都是同一种错误. 问题排查: 从异常信息里无法看出具体是哪里出了错误.只提示调用出现错误的地方.但是经过检查后明显错误不是再此处的代码. 经过每个问题文件进行移除,一次次运行进行排查问题最终找到了错误的地方,处于一个xml里面的

maps in java(java)

1 hashmap(abstractmap clonable serializable) 2 java.util.HashTable collection未有之前的array implementation,drooped,但是 thread safe,overhead thread写map即call put 时,另一thread必须等put完成.整个map将被locked.每个public method都有synchronized keyword 3