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 的问题

HashMap

  • 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的更多相关文章

  1. Java Maps的9个常见问题

    一般来说,Map是一种由键值对组成的数据结构,其中键(key)在Map中是不能重复的: 本篇文章总结了9个最常见的问题(关于Java Map及其实现类): 出于简单考虑,在代码例子中我将不使用泛型,因 ...

  2. Java开发者常犯的十个错误

    翻译自:Top 10 Mistakes Java Developers Make 文章列出了Java开发者最常犯的是个错误. 1.将数组转换为ArrayList 为了将数组转换为ArrayList,开 ...

  3. Top 10 Mistakes Java Developers Make(转)

    文章列出了Java开发者最常犯的是个错误. 1.将数组转换为ArrayList 为了将数组转换为ArrayList,开发者经常会这样做: ? 1 List<String> list = A ...

  4. Java 学习(21):Java 实例

    Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. Java 环境设置实例 //HelloWorld.java 文件 public cla ...

  5. python调用Java方法传入HashMap ArrayList

    1.Java代码: package com; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap ...

  6. jackson官方快速入门文档

    官方地址: http://jackson.codehaus.org/ http://wiki.fasterxml.com/JacksonInFiveMinutes http://wiki.faster ...

  7. Caching Best Practices--reference

    reference:http://java.dzone.com/articles/caching-best-practices There is an irresistible attraction ...

  8. Jackson - Quickstart

    JSON Three Ways Jackson offers three alternative methods (one with two variants) for processing JSON ...

  9. Scala入门指南与建议

    最近在学习使用Scala语言做项目,感觉这门语言实在是太优美了!作为一个本科数学.研究生机器学习专业的混合人才(哈哈),这门语言真的是满足了普通计算机编程(告诉计算机怎么做)和函数式编程(告诉计算机做 ...

随机推荐

  1. ARM中断处理过程

    以s3c2440  ARM9核为例: 一:s3c2440 ARM处理器特性: 1.S3C2440支持个中断源,含子中断源: 2.ARM9采用五级流水线方式: 3.支持外部中断和内部中断: 二.s3c2 ...

  2. 百度Web前端面试经历

    今天面了百度的前端实习职位.一面.时间大概是50分钟.面试官是位很帅气的小伙子,非常友好的一个人.进门的时候他让我等一会,我瞄了一眼他的电脑屏幕,发现他在coding…… 9点50开始的面试. 面试官 ...

  3. ios 网络/本地播放器

    推荐播放器: LRLAVPlayer相对易懂好修改,调整添加内容. https://github.com/codeWorm2015/videoPlayer NSString*path=[[NSBund ...

  4. vue.js随笔记---初识Vue.js

    1.基础要求: 1.1 HTML CSS JAVASCRIPT 1.2 模块化基础 1.3 Es6初步了解 2.vue.js 轻量级的MVVM模式框架,他同时吸收了recat和angular的优点,他 ...

  5. 推送一个已有的代码到新的 gerrit 服务器

    1.指定项目代码库中迭代列出全部ProductList(.git)到pro.log文件中 repo forall -c 'echo $REPO_PROJECT' | tee pro.log pro.l ...

  6. 三、Dotnet Core Code First 创建数据库

    1.在项目中创建Models文件夹2.在Models文件夹中建立 表的属性类:如 User类.3.在Models文件夹创建DataContext 继承DbContext类(可以选择重写OnModelC ...

  7. java 并发工具类CountDownLatch & CyclicBarrier

    一起在java1.5被引入的并发工具类还有CountDownLatch.CyclicBarrier.Semaphore.ConcurrentHashMap和BlockingQueue,它们都存在于ja ...

  8. Apache Spark1.1.0部署与开发环境搭建

    Spark是Apache公司推出的一种基于Hadoop Distributed File System(HDFS)的并行计算架构.与MapReduce不同,Spark并不局限于编写map和reduce ...

  9. Swing学习篇 API之JButton组件

    按钮(Jbutton) Swing中的按钮是Jbutton,它是javax.swing.AbstracButton类的子类,swing中的按钮可以显示图像,并且可以将按钮设置为窗口的默认图标,而且还可 ...

  10. jmeter导入DB数据再再优化

    前言:分享和规定命名规范后,各位测试人员一致认为这样jmeter的jmx文件限制太死,主要体现六方面: 第一:规定了一个jmx文件只能录入一个接口,这样会导致jmx文件很多 第二:导入DB的jmx文件 ...