java 8 lambda map_java8的lambda中的map相关操作

1. 介绍

本入门教程将介绍Java8中如何合并两个map。

更具体说来,我们将研究不同的合并方案,包括Map含有重复元素的情况。

2. 初始化

我们定义两个map实例

private static Map map1 = new HashMap<>();

private static Map map2 = new HashMap<>();

Employee类

public class Employee {

private Long id;

private String name;

// 此处省略构造方法, getters, setters方法

}

然后往map中存入一些数据

Employee employee1 = new Employee(1L, "Henry");

map1.put(employee1.getName(), employee1);

Employee employee2 = new Employee(22L, "Annie");

map1.put(employee2.getName(), employee2);

Employee employee3 = new Employee(8L, "John");

map1.put(employee3.getName(), employee3);

Employee employee4 = new Employee(2L, "George");

map2.put(employee4.getName(), employee4);

Employee employee5 = new Employee(3L, "Henry");

map2.put(employee5.getName(), employee5);

特别需要注意的是employee1 和 employee5在map中有完全相同的key(name)。

3. Map.merge()

Java8为java.util.Map接口新增了merge()函数。

merge()  函数的作用是: 如果给定的key之前没设置value 或者value为null, 则将给定的value关联到这个key上.

否则,通过给定的remaping函数计算的结果来替换其value。如果remapping函数的计算结果为null,将解除此结果。

First, let’s construct a new HashMap by copying all the entries from the map1:

首先,我们通过拷贝map1中的元素来构造一个新的HashMap

Map map3 = new HashMap<>(map1);

然后引入merge函数和合并规则

map3.merge(key, value, (v1, v2) -> new Employee(v1.getId(),v2.getName())

最后对map2进行迭代将其元素合并到map3中

map2.forEach(

(key, value) -> map3.merge(key, value, (v1, v2) -> new Employee(v1.getId(),v2.getName())));

运行程序并打印结果如下:

John=Employee{id=8, name='John'}

Annie=Employee{id=22, name='Annie'}

George=Employee{id=2, name='George'}

Henry=Employee{id=1, name='Henry'}

最终,通过结果可以看出,实现了两个map的合并,对重复的key也合并为同一个元素。

注意最后一个Employee的id来自map1而name来自map2.

原因是我们的merge函数的定义

(v1, v2) -> new Employee(v1.getId(), v2.getName())

4. Stream.concat()

Java8的Stream API 也为解决该问题提供了较好的解决方案。

首先需要将两个map合为一个Stream。

Stream combined = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream());

我们需要将entry sets作为参数,然后利用Collectors.toMap():将结果放到新的map中。

Map result = combined.collect(

Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

该方法可以实现map的合并,但是有重复key会报IllegalStateException异常。

为了解决这个问题,我们需要加入lambda表达式merger作为第三个参数

(value1, value2) -> new Employee(value2.getId(), value1.getName())

当检测到有重复Key时就会用到该lambda表达式。

现在把上面代码组合在一起:

Map result = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream())

.collect(Collectors.toMap(

Map.Entry::getKey,

Map.Entry::getValue,

(value1, value2) -> new Employee(value2.getId(), value1.getName())));

最终的结果

George=Employee{id=2, name='George'}

John=Employee{id=8, name='John'}

Annie=Employee{id=22, name='Annie'}

Henry=Employee{id=3, name='Henry'}

从结果可以看出重复的key“Henry”将合并为一个新的键值对,id取自map2,name取自map1。

5. Stream.of()

通过Stream.of()方法不需要借助其他stream就可以实现map的合并。

Map map3 = Stream.of(map1, map2)

.flatMap(map -> map.entrySet().stream())

.collect(Collectors.toMap(

Map.Entry::getKey,

Map.Entry::getValue,

(v1, v2) -> new Employee(v1.getId(), v2.getName())));

首先将map1和map2的元素合并为同一个流,然后再转成map。通过使用v1的id和v2的name来解决重复key的问题。

map3的运行打印结果如下:

6. Simple Streaming

我们还可以借助stream的管道操作来实现map合并。

Map map3 = map2.entrySet()

.stream()

.collect(Collectors.toMap(

Map.Entry::getKey,

Map.Entry::getValue,

(v1, v2) -> new Employee(v1.getId(), v2.getName()),

() -> new HashMap<>(map1)));

结果如下:

{John=Employee{id=8, name='John'},

Annie=Employee{id=22, name='Annie'},

George=Employee{id=2, name='George'},

Henry=Employee{id=1, name='Henry'}}

7. StreamEx

我们还可以使Stream API 的增强库

Map map3 = EntryStream.of(map1)

.append(EntryStream.of(map2))

.toMap((e1, e2) -> e1);

注意 (e1, e2) -> e1 表达式来处理重复key的问题,如果没有该表达式依然会报IllegalStateException异常。

结果:

{George=Employee{id=2, name='George'},

John=Employee{id=8, name='John'},

Annie=Employee{id=22, name='Annie'},

Henry=Employee{id=1, name='Henry'}}

8 总结

本文使用了Map.merge(), Stream API, StreamEx 库实现map的合并。

二:Java8使List转为Map

import com.yang.test.User;

import javax.jws.soap.SOAPBinding;

import java.util.*;

import java.util.function.Function;

import java.util.stream.Collectors;

public class Main {

public static void main(String[] args) {

List userlist = new ArrayList<>();

for (int i = 0; i <10; i++) {

userlist.add(new User("张三"+i,i));

}

System.out.println(getAllages(userlist).size());

System.out.println(getUser2Map(userlist));

System.out.println(getUser2MapUser(userlist));

System.out.println(getUser2MapUser2(userlist));

System.out.println(getUser2MapUser3(userlist));

}

public static List getAllages(Listuserlist){

return userlist.stream().map(user -> user.getAge()).collect(Collectors.toList());

}

public static Map getUser2Map(Listuserlist){

return userlist.stream().collect(Collectors.toMap(User::getAge,User::getName));

}

public static Map getUser2MapUser(Listuserlist){

return userlist.stream().collect(Collectors.toMap(User::getAge,User-> User));

}

/**

* 比较优雅的写法是这样的

* @param userlist

* @return

*/

public static Map getUser2MapUser2(Listuserlist){

return userlist.stream().collect(Collectors.toMap(User::getAge, Function.identity()));

}

/**

* 重复key的情况下 简单的使用后者覆盖前者的

*/

public static Map getUser2MapUser3(Listuserlist){

return userlist.stream().collect(Collectors.toMap(User::getAge, Function.identity(),(key1,key2)->key2));

}

/**

*指定map的具体实现

* @param userlist

* @return

*/

public static Map getUser2MapUser4(Listuserlist){

return userlist.stream().collect(Collectors.toMap(User::getAge, Function.identity(),(key1,key2)->key2, LinkedHashMap::new));

}

}

Function.identity()用的默认的也可以是x->x 即value是user

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值