在Stream流中将List转换为Map,是使用Collectors.toMap
方法来进行转换。
-
key和value都是对象中的某个属性值
Map<String, String> userMap = userList.stream().collect(Collectors.toMap(User::getId, User::getName));
说明:
userMap
为转换后的Map变量,userList
要进行转换的对象集合,User::getId
为要作为Map键的对象属性,User::getName
为要作为Map值的对象属性 -
key是对象中的某个属性值,value是对象本身(使用返回本身的lambda表达式)
Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, User -> User));
说明:
User -> User
:使用lambda实例化对象本身 -
key是对象中的某个属性值,value是对象本身(使用Function接口的简洁写法)
Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));
说明:
identity()
:Function接口的一个静态方法,返回一个输出跟输入一样的Lambda表达式对象,等价于形如t -> t
形式的Lambda表达式 -
使用
Collectors.toMap
时,抛出的Duplicate key问题分析:Duplicate key 即“重复键”,因为Map中key是唯一的,此时Collectors中的
toMap
方法不清楚取前值还是后值,故抛出异常解决方案:
-
保证List转Map时,key唯一(不推荐,代码问题不可使用业务去保证唯一)
-
使用后一个key的值覆盖前一个key的值
Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(), (oldValue, newValue) -> newValue));
说明:
Function.identity()
指定Map的Value值为对象本身,(oldValue, newValue) -> newValue)
即当key冲突是,将前一个key对应的对象本身的value,用后一个key的对象本身的value覆盖掉,即结果为形象为(key1,value2),(key2,value2) -
不进行覆盖,前一个与后一个重复时,key2取key1的value
Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(), (oldValue, newValue) -> oldValue));
说明:
(oldValue, newValue) -> oldValue)
即当key冲突时,取前一个key的对象本身的value为将后一个key对应的对象本身的value,即结果为形象为(key1,value1),(key2,value1) -
保留相同key彼此的值
Map<String, List<User>> map = userList.stream().collect(Collectors.toMap(User::getId, User -> { List<User> userArrayList = new ArrayList<>(); userArrayList.add(User); return userArrayList; }, (List<User> oldList, List<User> newList) -> { oldList.addAll(newList); return oldList; } ));
说明:保留相同key的不同value时,需要将List转为一个value为集合的Map,通过在lambda表达式的方法体中定义一个新的集合userArrayList来处理key相同时对User对象的添加,并将封装形同key的不同value的集合返回作为Map的value,转换的map测试结果为:
{1=[User{id='1', name='hello'}, User{id='1', name='world'}], 2=[User{id='2', name='hello world'}]}
-