【JAVA8】Map新方法,别再重复造车轮了_保护我方胖虎的博客-程序员宝宝_java8 map新方法

技术标签: java  java8  


java8 发布后,map类库增加了多个新的方法,利用这些新方法能更加便利地操纵Map中的数据

新增的方法有:

getOrDefault,forEach,compute,computeIfAbsent,computeIfPresent,merge,putIfAbsent,remove(key,value),replace,replaceAll

getOrDefault

getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。

语法:

hashmap.get(Object key, V defaultValue)

参数说明:

  • key - 键
  • defaultValue - 当指定的key并不存在映射关系中,则返回的该默认值

返回值:

返回 key 相映射的的 value,如果给定的 key 在映射关系中找不到,则返回指定的默认值。

模拟数据:

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);

java8之前的方式

Map<String, Integer> map = new HashMap<>(4);
map.put("lisa", 1);
int lisaValue = 0;
if (map.containsKey("lisa")) {
    
    lisaValue = map.get("lisa");
}
System.out.println(lisaValue);

java8

// key为 lisa 的映射存在则返回对应value,否则返回默认值-1
Integer java8lisaValue = map.getOrDefault("lisa", -1);
// 1
System.out.println(java8lisaValue);
// key为 adas 的映射存在则返回对应value,否则返回默认值-999
Integer adasValue = map.getOrDefault("adas", -999);
// adas
System.out.println(adasValue);

forEach

foreach 可以让我们以Lambda的方式快速遍历映射集(map)

语法:

map.forEach(BiConsumer<K, V> action)

参数说明:

  • BiConsumer- java8新提供的函数式接口,我们可以定义遍历消费逻辑

返回值:

模拟数据:

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);

java8之前的方式

这种是以前Map遍历获取键值对信息最高效的方式,因为每组键值对只需遍历一次,但写法较为古老

for (Map.Entry<String, Integer> entry : map.entrySet()) {
    
    System.out.println(entry.getKey() + "==" + entry.getValue());
}

java8

实际上Java8 map的foreach底层仍是用的entrySet,只是上层用了BiConsumer 函数式接口,简化了我们直接遍历的代码。

 map.forEach((k, v) -> System.out.println(k + "=" + v));

具体实现如下:

image-20210905104814367

compute

尝试计算指定键及其当前映射值的映射(如果没有当前映射,则返回null)

公式:

map.compute(K key, BiFunction remappingFunction)

参数说明:

  • key - 键
  • remappingFunction - 重新映射函数,用于重新计算值

返回值

如果 key 对应的 value 不存在,则返回该 null,如果存在,则返回通过 remappingFunction 重新计算后的值并保存到映射集中(如重新计算后的值为Null,不会保存,且会将该映射从映射集中删除)

模拟数据:

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);

java8 之前操作

private static Integer computeBefore(String key, Integer newValue) {
    
    Map<String, Integer> map = new LinkedHashMap<>(4);
    map.put("lisa", 1);
    map.put("jone", 2);
    map.put("selina", 3);
    Integer oldValue = map.get(key);
    if (newValue != null) {
    
        if (map.containsKey(key) && oldValue != null) {
    
            map.remove(key);
        }
        return null;
    } else {
    
        map.put(key, newValue);
        return newValue;
    }
}

java8操作

Key在Map中存在

// jone key存在,且 新value不为null,则会返回最新jone对应的value (v + 234),并添加到映射集map中
Integer joneNewValue = map.compute("jone", (k, v) -> v == null ? 0 : v + 234);
// joneNewValue:236
System.out.println("joneNewValue:" + joneNewValue);
// {lisa=1, jone=236, selina=3}
System.out.println(map);

System.out.println("================");
// jone key存在,且 新value为null,则会返回最新jone对应的value null,并将映射在原集中删除
Integer joneNewValue2 = map.compute("jone", (k, v) -> null);
// joneNewValue2:null
System.out.println("joneNewValue2:" + joneNewValue2);
// 此时会 移除 KEY  jone
// {lisa=1, selina=3}
System.out.println(map);

Key在Map中不存在

// asd key不存在,且 新value不为null,则会返回最新asd对应的value 111,并保存到映射集map中
Integer asdNewValue = map.compute("asd", (k, v) -> 111);
// asdNewValue:111
System.out.println("asdNewValue:" + asdNewValue);
// {lisa=1, selina=3, asd=111}
System.out.println(map);

System.out.println("================");
// box key不存在,且 新value为null,则会返回null, 不保存到映射集map中
Integer boxNewValue = map.compute("box", (k, v) -> null);
// boxNewValue:null
System.out.println("boxNewValue:" + boxNewValue);
// {lisa=1, selina=3, asd=111}
System.out.println(map);

computeIfAbsent

如果指定的KEY 的键值对(k,v)不存在,或者 对应的Value 为空,则将键值对新增至映射集(Map)中

语法:

map.computeIfAbsent(K key, Function remappingFunction)

参数说明:

  • key - 键
  • remappingFunction - 重新映射函数,用于重新计算值

返回值:

如果 key 对应的 value 不存在,则使用获取 remappingFunction 重新计算后的值,并保存为该 key 的 value,否则返回 value。

模拟数据:

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
map.put("ddd", null);

java8 之前操作

Integer lisaValue = map.get("adas");
if ( !map.containsKey("adas")|| map.get("adas") == null) {
    
    map.put("adas", 2345);
}

java8操作

// 原映射集无 key为 adas的键值对,且 新key  adas 对应的 value 不为null (2345) 则会将其添加到map映射集中并返回该值
Integer adas = map.computeIfAbsent("adas", x -> 2345);
// 2345
System.out.println(adas);
// {lisa=1, jone=2, selina=3, ddd=null, adas=2345}
System.out.println(map);

System.out.println("--------------");

// 原映射集无 key为 dml的键值对,且 新key  ml 对应的 value 为null,则忽略添加,并返回null
Integer dmlValue = map.computeIfAbsent("dml", x -> null);
// null
System.out.println(dmlValue);
// {lisa=1, jone=2, selina=3, ddd=null, adas=2345}
System.out.println(map);

System.out.println("--------------");
// 原映射集有 Key为 ddd的键值对,但ddd对应的value 为空,如果我们再次添加有效value到ddd,则会将原键值对覆盖
Integer dddNewValue = map.computeIfAbsent("ddd", x -> 0);
// 0
System.out.println(dddNewValue);
// {lisa=1, jone=2, selina=3, ddd=0, adas=2345}
System.out.println(map);

computeIfPresent

如果指定KEY的映射存在且Value非null,则将指定KEY的原Value,替换为现在的Value,保存存在映射集中,如果现Value为null,会将指定KEY的映射删除

语法:

map.computeIfPresent(K key, BiFunction remappingFunction)

参数说明:

  • key - 键
  • remappingFunction - 重新映射函数,用于重新计算值

返回值:

如果 key 对应的 value 不存在,则返回该 null,如果存在,则返回通过 remappingFunction 重新计算后的值。

模拟数据:

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
map.put("ddd", null);

java8之前操作

if (map.get("selina") != null) {
    
    Integer oldValue = map.get("selina");
    Integer newValue = 1232312;
    if (newValue != null) {
    
        map.put("selina", newValue);
    } else {
    
        map.remove("selina");
    } 
}

java8

// 原映射集中存在对应KEY  ,原Value不为null,现value不为null,则覆盖原来 键值对映射
Integer selinaNewValue = map.computeIfPresent("selina", (k, v) -> 888999);
// 888999
System.out.println(selinaNewValue);
// {lisa=1, jone=2, selina=888999, ddd=null}
System.out.println(map);

System.out.println("-------------------");
// 原映射集中存在对应KEY  ,原Value不为null,现value为null,则移除对应键值对
Integer selinaNewValue2 = map.computeIfPresent("selina", (k, v) -> null);
// null
System.out.println(selinaNewValue2);
// 移除了selina
System.out.println(map);

System.out.println("-------------------");
// 原映射集中存在对应KEY  ,原Value为null,现value 不为null,  对原映射集不做任何操作
Integer dddNewValue = map.computeIfPresent("ddd", (k, v) -> 2222222);
System.out.println(dddNewValue);
System.out.println(map);

System.out.println("-------------------");
// 原映射集中不存在对应KEY  ,现value 不为null  对原映射集不做任何操作
Integer mqNewValue = map.computeIfPresent("mq", (k, v) -> -1);
System.out.println(mqNewValue);
System.out.println(map);

merge

merge() 方法会先判断指定的 key 是否存在,如果不存在,则添加键值对到 hashMap 中,如果存在则根据逻辑重新映射该KEY键值对(如何合并相同KEY的新旧VALUE)

语法:

map.merge(key, value, remappingFunction)

参数说明:

  • key - 键
  • value - 值
  • remappingFunction - 重新映射函数,用于重新计算值

返回值:

如果 key 对应的 value 不存在,则返回该 value 值,如果存在,则返回通过 remappingFunction 重新计算后的值。

模拟数据:

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
map.put("ddd", null);

我们都知道,Map 的KEY,如果相同了,后插入的值会覆盖新的值

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
// {lisa=1, jone=2, selina=3}
System.out.println(map);
map.put("lisa", 2);
// {lisa=2, jone=2, selina=3}
System.out.println(map);

merge,可以让我们根据自己选择如何处理相同KEY的值,类似于冲突合并(怎么合并,自己决定)

// 采用旧值
map.merge("lisa", 100, (oldValue, newValue) -> oldValue);

// 采用新值
map.merge("lisa", 100, (oldValue, newValue) -> newValue);

// 新旧值逻辑处理合并
map.merge("lisa", 100, (oldValue, newValue) -> oldValue + newValue);
  map.merge("lisa", 100, Integer::sum);

注意:

java8 Stream Collectors.toMap() 方法便要我们去合并冲突,否则如果出现相同KEY的数据,或者Value为null,程序会报错!

User adas = new User("adas", 23);
User adas2 = new User("adas", 28);
User mlg = new User("mlg", 34);
ArrayList<User> list = new ArrayList<>();
list.add(adas);
list.add(adas2);
list.add(mlg);
Map<String, Integer> userMap = list.stream().collect(Collectors.toMap(User::getName, User::getValue));
System.out.println(userMap);

提示我们键冲突了!

image-20210905135211281

解决:

Map<String, Integer> userMap = list.stream()
        .filter(x->x.name!=null && x.value!=null)
        // 这里采用新值覆盖旧值
        .collect(Collectors.toMap(User::getName, User::getValue,(oldValue,newValue)->newValue));
// {adas=28, mlg=34}
System.out.println(userMap);

putIfAbsent

putIfAbsent() 方法会先判断指定的键(key)是否存在,不存在则将键/值对插入到映射集中,并返回null,存在则返回原本Value

语法:

map.putIfAbsent(K key, V value)

参数说明:

  • key - 键
  • value - 值

返回值:

如果所指定的 key 已经在Map 中存在,返回和这个 key 值对应的 value, 如果所指定的 key 在Map 中不存在,则返回 null。

注意如果指定 key 之前已经和一个 null 值相关联了 ,则该方法也返回 null。

模拟数据:

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);

java8 之前写法

Integer newValue = 222;
Integer joneValue = map.get("jone");
if (joneValue == null) {
    
    joneValue = map.put("lisa", newValue);
} else {
    
    joneValue = joneValue;
} 

java8

// selina 在源映射集中不存在,则返回null 做插入操作
Integer adasValue = map.putIfAbsent("adas", 1);
System.out.println(adasValue);
System.out.println(map);

System.out.println("----------");

// selina 在源映射集中存在,则返回原值 不做插入操作
Integer selinaValue = map.putIfAbsent("selina", 33333);
System.out.println(selinaValue);
System.out.println(map);

remove(key,value)

当指定的 KEY 与VALUE 在映射集中存在,且为绑定的键值对关系时,才移除

语法:

map.remove(K key, V value)

参数说明:

  • key - 键
  • value - 值

返回值:

仅当 key-value 映射存在,且二者为绑定关系时,才会移除该数据,返回true,其他情况为false

模拟数据:

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);

演示

// lisa-2 无映射关系,因为不会移除
map.remove("lisa", 2);
// {lisa=1}
System.out.println(map);

replace

replace() 方法替换 映射集中是指定的 key 对应的 value。

语法:

map.replace(K key, V oldValue, V newValue)

参数说明:

  • key - 键
  • oldValue - 旧的 value 值
  • newValue - 新的 value 值

返回值:

如果 oldValue 不存在,对 key 对应对 value 执行替换,返回 key 对应的旧值,如果存在则替换,并返回旧值。

如果 KEY 不存在,则不做任何操作,返回null

模拟数据:

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);

演示

// key 存在 且原 value 不为null
Integer lisaOldValue = map.replace("lisa", 333);
// 返回原来旧值 1
System.out.println(lisaOldValue);
// lisa的值已被替换  {lisa=333, hobo=null}
System.out.println(map);

System.out.println("___________________");

// key 存在 且原 value 为null
Integer hoboOldValue = map.replace("hobo", -1);
// 返回旧值 null
System.out.println(hoboOldValue);
// hobo的值已被替换 {lisa=333, hobo=-1}
System.out.println(map);
System.out.println("___________________");

// key 不存在
Integer adasOldValue = map.replace("adas", -1);
// null
System.out.println(adasOldValue);
// 未变 {lisa=333, hobo=-1}
System.out.println(map);

replaceAll

replaceAll() 方法将 映射集中的所有映射Value替换成给定的函数所执行的结果

语法:

map.replaceAll(Bifunction<K, V> function)

**注:**hashmap 是 HashMap 类的一个对象。

参数说明:

  • function - 函数式接口实例,生成映射对函数

返回值:

无,只会对映射集中的值做替换处理。

模拟数据:

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
map.put("qq", null);

演示

// replaceAll之前:{lisa=1, jone=2, selina=3, qq=null}
System.out.println("replaceAll之前:" + map);
map.replaceAll((k, v) -> v == null ? -1 : v * 100);

// replaceAll之后:{lisa=100, jone=200, selina=300, qq=-1}
System.out.println("replaceAll之后:" + map);

values

values() 方法返回映射中所有 value 组成的集合

语法:

hashmap.values()

参数说明:

返回值:

返回 Map 中所有 value 值所组成的集合

模拟数据:

Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
map.put("qq", null);

演示

// [lisa, jone, selina, qq]
System.out.println(map.keySet());
// [1, 2, 3, null]
System.out.println(map.values());
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/leilei1366615/article/details/120114749

智能推荐

c语言在屏幕上显示字符,求C语言高手帮忙解答1、在屏幕上显示一行字符串:”hello world!”。2、从键盘上输入两个数,放入整型变量a,b当中,求两数之和c=a+b,两数之差d=a-b。3、从键..._Matt小特的博客-程序员宝宝

求C语言高手帮忙解答1、在屏幕上显示一行字符串:”hello world!”。2、从键盘上输入两个数,放入整型变量a,b当中,求两数之和c=a+b,两数之差d=a-b。3、从键盘上输入一个数,放入双精度型变量m中,求m的余弦值、绝对值、平方根值。4、由键盘输入两个数,输出其中的较小数。5、求累加和的值:从键盘上输入一个整数,放入变量n中,求C=1+2+3+4+5+……+n。6、从键盘上输入圆的半径...

3D数学笔记——任意轴旋转_混沌-均衡-进化的博客-程序员宝宝_任意轴旋转

——题记公式: v ′ = (v · n) n+(v - (v · n) n)cos(θ)+sin(θ)(u x v)表示三维空间旋转的方法有很多,这里关注轴角式,并采用右手坐标系;如图:有旋转轴 u = (x、y、z),我们希望向量v,沿着这个旋转轴旋转θ度,变换到v ′。我们来变换一下v ′;1. 旋转的分解 首先,我们可以将v...

不用linux转录组数据分析,无参考基因组的转录组测序分析流程_师敬超的博客-程序员宝宝

下边上干货.1.分析流程:2.分析步骤2.1数据预处理,质控过程,与有参考的转录组分析一致2.2 UniGene拼接目的:将预处理后reads进行拼接,得到拼接结果。原理:应用de Bruijn graph path算法对reads进行denovo拼接;对上一步的拼接结果,再用Hamilton Path算法拼接。结果:UniGene序列,UniGene统计信息,序列长度分布图2....

如何Axure7.0 中制作锚点效果_御米的博客-程序员宝宝

1.      首先放置一个动态面板,命名为菜单栏,然后固定到浏览器上,如图所示

redmine安装webhook_weixin_34279061的博客-程序员宝宝

2019独角兽企业重金招聘Python工程师标准&gt;&gt;&gt; ...

图片相似度计算 3---(dhash--c++实现)_zhangshen12356的博客-程序员宝宝

前面两篇博客介绍了均值哈希算法(ahash)、感知哈希算法(phash)。由前面的介绍可知,ahash算法是基于比较灰度图每个像素与所有像素点的平均值来实现的,最适合用于缩略图,放大搜索在本质上是对颜色作比较。phash由于做了DCT操作,本质上是对频率的比较。下面要介绍的图像差异哈希算法(dhash)是通过对比相邻像素像素值的差异,即逐像素得到当前像素与右邻像素的差值,得到一个图像差异矩阵,通过该矩阵生成哈希值。这个逐像素得到的图像差异矩阵的比原像素矩阵少了一列,即宽度比原像素矩阵少了1,高度不变。下

随便推点

Shader内置函数(方便自己看)_SnoopyNa2Co3的博客-程序员宝宝_shader 内置函数

一、内置包含文件  Unity中有类似于C++的包含文件.cginc,在编写Shader时我们可以使用#include指令把这些文件包含进来这样我们就可以使用Unity为我们提供的一些非常好用的函数、宏和变量。例如:#include&quot;UnityCG.cginc&quot;包含文件的位置:根目录\Editor\Data\CGIncludes知识点1:以下是Unity中常用包含文件:  文件...

QT中自动补全、自动提示、自动补缺中各个图标的含义_qq_25139081的博客-程序员宝宝

QT中自动补全、自动提示、自动补缺中各个图标的含义欢迎使用Markdown编辑器你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。新的改变我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:全新的界面设计 ,将会带来全新的写作体验;在创作中心设置你喜爱的代码高亮样式,Markdown

R语言quantmod包_troubleisafriend的博客-程序员宝宝_r语言中quantmod包

获取数据getSymbols()从多种信息源里获得信息   getSymbols.csv()从csv文件中读入数据getDividends() 获取上市公司的信息数据 getSymbols.FRED() 从FRED中获取数据getFinancials() 获取上市公司的财务报表 getSymbols.google() 从google中获取数据getFX()获取汇率数据      

Reactor模式_qq_20853741的博客-程序员宝宝

一、Reactor模式的应用场景反应器设计模式(Reactor pattern)是一种为处理并发服务请求,并将请求提交到一个或者多个服务处理程序的事件设计模式。当客户端请求抵达后,服务处理程序使用多路分配策略,由一个非阻塞的线程来接收所有的请求,然后派发这些请求至相关的工作线程进行处理。那么,什么场景下使用Reactor模式?对于高并发系统,常会使用Reactor模式,其代替了常用的多线程处理方式,节省系统的资源,提高系统的吞吐量。下面用比较直观的形式来介绍这种模式的使用场景。以餐.

jquery完成列表中数据选择,以及进行所选数据的再选择_Lingfeng928的博客-程序员宝宝

代码如下:Jquery实现角色左右选择特效#one{width:200px; height:180px; float:left}#two{width:50px; height:180px; float:left}#three{width:200px; height:180px; float:left}.btn{width:50px; height:30p

Android :task 与 back stack解读之进阶之路.(包括 task,back stack,lauchMode, taskAffinity ,intent flags等解析)_sddyljsx的博客-程序员宝宝

二、进阶之路        通过上面的介绍,我们对Android的task,back stack有了一定的了解,一般来讲,我们不用去关注activity是怎么被放入task的,以及在back stack的存储状态。但是,有时候我们也会有一些特殊的需求。比如说,在一个新的activity启动时,我们想把它放进一个新的task中;或者启动一个activity时,我们不希望创建一个新的实例,而是使用

推荐文章

热门文章

相关标签