Java ConcurrentHashMap的使用示例

构造方法

// 1.无参数构造方法
new ConcurrentHashMap();

// 2.指定初始容量
new ConcurrentHashMap(initialCapacity)

// 3.指定初始容量和加载因子
new ConcurrentHashMap(initialCapacity,loadFactor)

// 4.指定初始容量和加载因子与并发级别(并发更新线程数)
new ConcurrentHashMap(initialCapacity, loadFactor, concurrencyLevel)

// 5.创建与给定映射具有相同映射的新映射
new ConcurrentHashMap(Map<? extends K, ? extends V> m)

方法介绍

新增元素

// 1.添加元素,不允许null
map.put(1,1);

// 2.添加一个map
map.putAll(map);
// 3.添加元素, 键不存在映射关系才添加成功
map.putIfAbsent(2,1);

删除元素

// 1.移除指定的key
map.remove(1);
// 2.移除指定的key,value
map.remove(2,2);

替换元素

// 1.替换指定key
map.replace(1,3);

// 2.替换指定key,value
map.replace(1,2,4);

// 3.替换所有,这里是把value都乘以2
map.replaceAll((key,value)->value << 1);

查找元素

// 1.返回到指定键所映射的值
map.get("精灵王");

// 2. 返回指定键映射到的值,如果此映射不包含该键的映射,则返回给定的默认值。
map.getOrDefault("精灵王","jinglingwang.cn");

// 指定搜素函数
// 1.通过在每个(键,值)上应用给定的搜索函数返回非空结果,如果没有则返回null。
//   成功后,进一步的元素处理被抑制,并且搜索功能的任何其他并行调用的结果被忽略。
Object a = map.search(5,(key,value)->{
    return (value & 1) == 0 ? value : null; // 查找第一个偶数,如果是奇数返回null
});

// 2. 每个键上应用给定搜索函数的非null结果,如果没有则返回null。
String k = map.searchKeys(5,(key)->{
    return "jinglingwang".equals(key) ? key : null;
});
System.out.println(k);

// 3. 对每个值应用给定的搜索函数,如果没有,返回null。
Integer v2 = map.searchValues(5,(value)->{
    return value == 2 ? 520 : null;
});
System.out.println(v2);

// 4.从每个entry应用给定的搜索函数,如果没有,则返回null。
Integer a = map.searchEntries(5,(entry)->{
    System.out.println("entry:"+entry.getKey() + "   " + entry.getValue());
    return "jinglingwang.cn".equals(entry.getKey()) ? 1 : null;
});
System.out.println(a);

包含

// 1. 验证值是否存在, 等同于map.containsValue()方法
map.contains(4)

// 2. 验证key是否存在
map.containsKey("精灵王")

// 3. 验证值是否存在,等同于map.contains()方法
map.containsValue(4)

遍历

// 1.返回此表中键的枚举
map.keys();

// 2.返回此地图中包含的键的Set视图
map.keySet();

// 3.返回此地图中键的Set视图,使用给定的映射值
map.keySet(100)

// 4. 返回此表中值的枚举。
map.elements();

// 5.返回此地图中包含的映射的Set视图。
map.entrySet().forEach((entry)->{
    System.out.println(entry.getKey() + " " + entry.getValue());
});

// 6.1 同时遍历key,value
map.forEach((key,value)->{
    System.out.println(key+ " " + value);
});
// 6.2 同时遍历key,value,找到满足条件的执行响应函数
map.forEach(5,(key,value)->{
    System.out.println(key+ " " + value);
    return (value & 1) == 0 ? "jinglingwang.cn" : null;
},aa->{
    System.out.println(aa); // 条件中有偶数,每次就输出jinglingwang.cn
});

// 7.1遍历
map.forEachEntry(5,(entry)->{
    System.out.println(entry.getKey() + " " + entry.getValue());
});

// 7.2遍历查找,满足条件执行响应的函数
map.forEachEntry(5,(entry)->{
    System.out.println(entry.getKey() + " " + entry.getValue());
    return (value & 1) == 0 ? "jinglingwang.cn" : null;
},aa->{
    System.out.println(aa); // 条件中有偶数,每次就输出jinglingwang.cn
});

// 8.1遍历key
map.forEachKey(5,key->{
    System.out.println("key: " + key);
});
// 8.2遍历key,满足条件的key执行响应的函数
map.forEachKey(5,key->{
    System.out.println("key: " + key);
    return !key.equals("jinglingwang") ? "jinglingwang.cn" : null;
},kk ->{
    System.out.println(kk);
});

// 9.1 遍历value
map.forEachValue(5,value->{
    System.out.println("value: " + value);
});
// 9.2 遍历value,满足条件的value执行响应的函数
map.forEachValue(5,value->{
    System.out.println("value: " + value);
    return (value & 1) == 0 ? "jinglingwang.cn" : null;
},vv ->{
    System.out.println(vv);
});

reduce归约

reduce()

//新增元素
map.put("1",0);
map.put("2",4);
map.put("3",6);
map.put("4",8);
// 1. 返回使用给定的reducer组合值来累积所有(键,值)对的给定转换的结果,如果没有,则返回null
String res =  map.reduce(5,(key,value)->{
    System.out.println("transformer key:"+key+" value:"+value);
    return value+"";
},(key,value)->{
    System.out.println("reducer key:"+key+" value:"+value);
    return key+value+"";
});
System.out.println("res:"+res);

以上示例输出如下:

transformer key:1 value:0
transformer key:2 value:4
reducer key:0 value:4
transformer key:3 value:6
reducer key:04 value:6
transformer key:4 value:8
reducer key:046 value:8
res:0468

第一个transformer函数遍历整个map,然后将返回值传递到reduce函数进行计算,之后reduce函数的返回值再次参与到下一次的reduce函数的计算中。

reduceToDouble()

double reduceToDouble = map.reduceToDouble(5,(key,value)->{
    System.out.println("transformer key:"+key);
    return value;
},100,(key,value)->{
    System.out.println("reducer key:"+key+" value:"+value);
    return key+value;
});
System.out.println("reduceToDouble:"+reduceToDouble);
// 输出结果
transformer key:1 value:0
reducer key:100.0 value:0.0
transformer key:2 value:4
reducer key:100.0 value:4.0
transformer key:3 value:6
reducer key:104.0 value:6.0
transformer key:4 value:8
reducer key:110.0 value:8.0
reduceToDouble:118.0

遍历归约所有的键值对,并把结果转换成double类型。

类似的方法还有reduceToInt()和reduceToLong()。

reduceEntries()

// 第一种,返回值为entry
Map.Entry reduceEntries =  map.reduceEntries(5,entry->{
    System.out.println("transformer key:"+entry.getKey()+" value:"+entry.getValue());
    return entry;
},(key,value)->{
    System.out.println("reducer key:"+key+" value:"+value);
    return value;
});
System.out.println("reduceEntries:"+reduceEntries);
// 输出如下
transformer key:1 value:0
transformer key:2 value:4
reducer key:1=0 value:2=4
transformer key:3 value:6
reducer key:2=4 value:3=6
transformer key:4 value:8
reducer key:3=6 value:4=8
reduceEntries:4=8

// 第二种
String reduceEntries2 =  map.reduceEntries(5,(entry)->{
    System.out.println("transformer key:"+entry.getKey()+" value:"+entry.getValue());
    return entry.getValue()+"";
},(key,value)->{
    System.out.println("reducer key:"+key+" value:"+value);
    return key+value+"";
});
System.out.println("reduceEntries2:"+reduceEntries2);
transformer key:1 value:0
transformer key:2 value:4
reducer key:0 value:4
transformer key:3 value:6
reducer key:04 value:6
transformer key:4 value:8
reducer key:046 value:8
reduceEntries2:0468

transformer 函数每次返回的是一个entry,然后会传入到reduce函数中,reduce的return值会继续传递到下一次的reduce计算。

reduceEntriesToDouble()

// 返回使用给定的reducer累加给定变换的结果,以组合值,给定基础作为一个标识值
Double reduceEntriesToDouble = map.reduceEntriesToDouble(5,entry->{
    System.out.println("transformer key:"+entry.getKey()+" value:"+entry.getValue());
    return Double.valueOf(entry.getValue());
},100,(l,r)->{
    System.out.println("reducer key:"+l+" value:"+r);
    return l+r;
});
System.out.println("reduceEntriesToDouble:"+reduceEntriesToDouble);
// 输出结果
transformer key:1 value:0
reducer key:100.0 value:0.0
transformer key:2 value:4
reducer key:100.0 value:4.0
transformer key:3 value:6
reducer key:104.0 value:6.0
transformer key:4 value:8
reducer key:110.0 value:8.0
reduceEntriesToDouble:118.0

其中transformer函数是以entry的形式来进行遍历的,第三个参数是一个归约的标识(初始默认值),功能和reduceEntriesToInt()和reduceEntriesToLong()两个方法非常相似。

reduceKeys()

// 1.第一种,只有reduce函数,遍历所有的键值对,reduce函数的返回值会作为下一次的key,如果没有则返回null。
String newKey = map.reduceKeys(5,(key,value)->{
    System.out.println("reducer key:"+key+" value:"+value);
    return key+value;
**}**);
System.out.println("newKey:"+newKey);
// 输出结果
reducer key:1 value:2
reducer key:12 value:3
reducer key:123 value:4
newKey:1234

// 2.第二种,有transformer和reducer
String newValue = map.reduceKeys(5,(key)->{
    System.out.println("transformer key:"+key);
    return key;
},(key,value)->{
    System.out.println("reducer key:"+key+" value:"+value);
    return key+value;
});
System.out.println("newValue:"+newValue);
// 输出结果
transformer key:1
transformer key:2
reducer key:1 value:2
transformer key:3
reducer key:12 value:3
transformer key:4
reducer key:123 value:4
newValue:1234

reduceKeysToDouble()

double reduceKeysToDouble = map.reduceKeysToDouble(5,(key)->{
    System.out.println("transformer key:"+key);
    return Double.parseDouble(key);
},100,(key,value)->{
    System.out.println("reducer key:"+key+" value:"+value);
    return key+value;
});
System.out.println("reduceKeysToDouble:"+reduceKeysToDouble);

遍历归约所有的key,并把结果转换成double类型。

类似的方法还有reduceKeysToInt()和reduceKeysToLong()。

reduceValues()

// 第一种:仅reducer函数
double reduceValues = map.reduceValues(5,(key,value)->{
    System.out.println("reducer key:"+key+" value:"+value);
    return key+value;
});
System.out.println("reduceValues:"+reduceValues);
//输出结果
reducer key:0 value:4
reducer key:4 value:6
reducer key:10 value:8
reduceValues:18.0

// 第二种,含有transformer
double reduceValues2 = map.reduceValues(5,(value)->{
    System.out.println("transformer value:"+value);
    return Double.valueOf(value);
},(key,value)->{
    System.out.println("reducer key:"+key+" value:"+value);
    return key+value;
});
System.out.println("reduceValues2:"+reduceValues2);
// 输出结果
transformer value:0
transformer value:4
reducer key:0.0 value:4.0
transformer value:6
reducer key:4.0 value:6.0
transformer value:8
reducer key:10.0 value:8.0
reduceValues2:18.0

reduceValuesToDouble()

double reduceValuesToDouble = map.reduceValuesToDouble(5,(value)->{
    System.out.println("transformer value:"+value);
    return Double.valueOf(value);
},100,(l,r)->{
    System.out.println("reducer key:"+l+" value:"+r);
    return l+r;
});
System.out.println("reduceValuesToDouble:"+reduceValuesToDouble);
// 输出结果
transformer value:0
reducer key:100.0 value:0.0
transformer value:4
reducer key:100.0 value:4.0
transformer value:6
reducer key:104.0 value:6.0
transformer value:8
reducer key:110.0 value:8.0
reduceValuesToDouble:118.0

遍历归约所有的value,并把结果转换成double类型。

类似的方法还有reduceValuesToInt()和reduceValuesToLong()。

以上就是Java ConcurrentHashMap的使用示例的详细内容,更多关于Java ConcurrentHashMap的资料请关注我们其它相关文章!

(0)

相关推荐

  • 深入学习java并发包ConcurrentHashMap源码

    正文 以前写过介绍HashMap的文章,文中提到过HashMap在put的时候,插入的元素超过了容量(由负载因子决定)的范围就会触发扩容操作,就是rehash,这个会重新将原数组的内容重新hash到新的扩容数组中,在多线程的环境下,存在同时其他的元素也在进行put操作,如果hash值相同,可能出现同时在同一数组下用链表表示,造成闭环,导致在get时会出现死循环,所以HashMap是线程不安全的. JDK1.7的实现 整个 ConcurrentHashMap 由一个个 Segment 组成,Seg

  • java ConcurrentHashMap锁分段技术及原理详解

    一.背景: 线程不安全的HashMap 因为多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap. 效率低下的HashTable容器 HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下.因为当一个线程访问HashTable的同步方法时,其他线程访问HashTable的同步方法时,可能会进入阻塞或轮询状态.如线程1使用put进行添加元素,线程2不但不能

  • JAVA核心知识之ConcurrentHashMap源码分析

    1 前言 ConcurrentHashMap是基于Hash表的Map接口实现,键与值均不允许为NULL,他是一个线程安全的Map.同时他也是一个无序的Map,不同时间进行遍历可能会得到不同的顺序.在JDK1.8之前,ConcurrentHashMap使用分段锁以在保证线程安全的同时获得更大的效率.JDK1.8开始舍弃了分段锁,使用自旋+CAS+sync关键字来实现同步.本文所述便是基于JDK1.8. ConcurrentHashMap与HashMap有共同之处,一些HashMap的基本概念与实现

  • Java源码解析ConcurrentHashMap的初始化

    首先看一下代码 private final Node<K,V>[] initTable() { Node<K,V>[] tab; int sc; while ((tab = table) == null || tab.length == 0) { // 第一次检查 if ((sc = sizeCtl) < 0) Thread.yield(); // lost initialization race; just spin else if (U.compareAndSwapInt

  • Java中遍历ConcurrentHashMap的四种方式详解

    这篇文章主要介绍了Java中遍历ConcurrentHashMap的四种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 方式一:在for-each循环中使用entries来遍历 System.out.println("方式一:在for-each循环中使用entries来遍历");for (Map.Entry<String, String> entry: map.entrySet()) { System.out.pr

  • java中ConcurrentHashMap的读操作为什么不需要加锁

    前言 ConcurrentHashMap是Java 5中支持高并发.高吞吐量的线程安全HashMap实现. 我们知道,ConcurrentHashmap(1.8)这个并发集合框架是线程安全的,当你看到源码的get操作时,会发现get操作全程是没有加任何锁的,这也是这篇博文讨论的问题--为什么它不需要加锁呢? 下面话不多说了,来一起看看详细的介绍吧 ConcurrentHashMap的简介 我想有基础的同学知道在jdk1.7中是采用Segment + HashEntry + ReentrantLo

  • Java并发系列之ConcurrentHashMap源码分析

    我们知道哈希表是一种非常高效的数据结构,设计优良的哈希函数可以使其上的增删改查操作达到O(1)级别.Java为我们提供了一个现成的哈希结构,那就是HashMap类,在前面的文章中我曾经介绍过HashMap类,知道它的所有方法都未进行同步,因此在多线程环境中是不安全的.为此,Java为我们提供了另外一个HashTable类,它对于多线程同步的处理非常简单粗暴,那就是在HashMap的基础上对其所有方法都使用synchronized关键字进行加锁.这种方法虽然简单,但导致了一个问题,那就是在同一时间

  • Java 中ConcurrentHashMap的实现

    ConcurrentHashMap(简称CHM)是在Java 1.5作为Hashtable的替代选择新引入的,是concurrent包的重要成员.在Java 1.5之前,如果想要实现一个可以在多线程和并发的程序中安全使用的Map,只能在HashTable和synchronized Map中选择,因为HashMap并不是线程安全的.但再引入了CHM之后,我们有了更好的选择.CHM不但是线程安全的,而且比HashTable和synchronizedMap的性能要好.相对于HashTable和sync

  • java 使用ConcurrentHashMap和计数器实现锁

    java 使用ConcurrentHashMap和计数器实现锁 在某些场景下,我们想让线程根据某些业务数据进行排队,简单代码如下: import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.Ato

  • Java7和Java8中的ConcurrentHashMap原理解析

    Java7 中 ConcurrentHashMap ConcurrentHashMap 和 HashMap 思路是差不多的,但是因为它支持并发操作,所以要复杂一些. 整个 ConcurrentHashMap 由一个个 Segment 组成,Segment 代表"部分"或"一段"的意思,所以很多地方都会将其描述为分段锁.注意,行文中,我很多地方用了"槽"来代表一个 segment. 简单理解就是,ConcurrentHashMap 是一个 Segm

  • Java concurrency集合之ConcurrentHashMap_动力节点Java学院整理

    ConcurrentHashMap介绍 ConcurrentHashMap是线程安全的哈希表.HashMap, Hashtable, ConcurrentHashMap之间的关联如下: HashMap是非线程安全的哈希表,常用于单线程程序中. Hashtable是线程安全的哈希表,它是通过synchronized来保证线程安全的:即,多线程通过同一个"对象的同步锁"来实现并发控制.Hashtable在线程竞争激烈时,效率比较低(此时建议使用ConcurrentHashMap)!因为当一

  • java基于ConcurrentHashMap设计细粒度实现代码

    细粒度锁: java中的几种锁:synchronized,ReentrantLock,ReentrantReadWriteLock已基本可以满足编程需求,但其粒度都太大,同一时刻只有一个线程能进入同步块,这对于某些高并发的场景并不适用.比如银行客户a向b转账,c向d转账,假如这两个线程并发,代码其实不需要同步.但是同时有线程3,e向b转账,那么对b而言必须加入同步.这时需要考虑锁的粒度问题,即细粒度锁. 网上搜寻了一些关于java细粒度锁的介绍文章,大部分是提供思路,比如乐观锁,String.i

  • 基于Java并发容器ConcurrentHashMap#put方法解析

    jdk1.7.0_79 HashMap可以说是每个Java程序员用的最多的数据结构之一了,无处不见它的身影.关于HashMap,通常也能说出它不是线程安全的.这篇文章要提到的是在多线程并发环境下的HashMap--ConcurrentHashMap,显然它必然是线程安全的,同样我们不可避免的要讨论散列表,以及它是如何实现线程安全的,它的效率又是怎样的,因为对于映射容器还有一个Hashtable也是线程安全的但它似乎只出现在笔试.面试题里,在现实编码中它已经基本被遗弃. 关于HashMap的线程不

随机推荐