Java8通过Stream将List转换成Map类型
2024年4月12日
- Java提供的api接口
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
/**
第一个参数是一个函数接口,使用输入的类型用来生成Key
*/
(Function<? super T, ? extends K> keyMapper
/**
第二个参数也是一个函数接口,使用输入的类型用来生成Value
*/
Function<? super T, ? extends U> valueMapper
举例说明
/*
Function.identit()是Function提供的个静态方法也可以使用lambda:e->e
*/
@Test
public void test01(){
List<String> names = Arrays.asList("tom","jack","jerry");
Map<String, Integer> collect = names.stream().collect(toMap(Function.identity(), String::length));
System.out.println(collect);
}
这个有一个致命的问题,很容易出现Key的冲突,这个代码就会报错,例如:
@Test
public void test02(){
List<String> names = Arrays.asList("tom","jack","jerry","tom");
Map<String, Integer> collect = names.stream().collect(toMap(Function.identity(), String::length));
System.out.println(collect)
}
/*
因为List包含两个tom,转成Map会有两个同样的Key,这个是不允许的。所以会报错:
java.lang.IllegalStateException: Duplicate key 3
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1254)
*/
2.Java提供的另一个api
/*
BinaryOpera 同样是一个函数式接口(U,U) ->U
在转map时可以让开发人员约定如何处理
*/
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction) {
return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}
举例说明
/*
保留第一个,后面的丢弃
*/
@Test
public void test03(){
List<String> names = Arrays.asList("tom","jack","jerry","tom");
Map<String, Integer> collect = names.stream().collect(toMap(Function.identity(), String::length,(e1,e2)->e1));
System.out.println(collect);
}
/*
保留最新的,覆盖之前的
*/
@Test
public void test04(){
List<String> names = Arrays.asList("tom","jack","jerry","tom");
Map<String, Integer> collect = names.stream().collect(toMap(Function.identity(), String::length,(e1,e2)->e2));
System.out.println(collect);
}
/*
如果全部保留,必须使用容器,Value就要是集合类型,对应Key不冲突的,容器只有一个元素
对应Key冲突的容器会有多个元素。
*/
@Test
public void test05() {
List<String> names = Arrays.asList("tom", "jack", "jerry", "tom");
Map<String, List<Integer>> collect = names.stream().collect(toMap(Function.identity(),
e -> {
List<Integer> list = new ArrayList<>();
list.add(e.length());
return list;
},
(e1, e2) -> {
e1.addAll(e2);
return e1;
}
));
System.out.println(collect);
}
3.Java提供的另一个api
/*
Supplier<M> mapSupplier 同样时一个函数式接口,用来返回一个容器
之前的代码都有包含一段:HashMap::new,代表toMap返回的默认时HashMap
这个参数让开发人员可以根据实际需要替换其他的容器
*/
public static <T, K, U, M extends Map<K, U>>
Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapSupplier) {
BiConsumer<M, T> accumulator
= (map, element) -> map.merge(keyMapper.apply(element),
valueMapper.apply(element), mergeFunction);
return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}
举例说明
@Test
public void test06() {
List<String> names = Arrays.asList("tom", "jack", "jerry", "tom");
Map<String, List<Integer>> collect = names.stream().collect(toMap(Function.identity(),
e -> {
List<Integer> list = new ArrayList<>();
list.add(e.length());
return list;
},
(e1, e2) -> {
e1.addAll(e2);
return e1;
},
LinkedHashMap::new
));
System.out.println(collect.getClass());
System.out.println(collect);
}