List< T > -> Map< T, T >
List< Integer> -> Map< Integer,Integer>
代码示例(本示例是存在重复key,并且会以首个出现的 key 去覆盖后面出现的冲突 key):
@Test
public void testList2() {
List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 4, 5, 6, 7, 8,1);
Map<Integer, Integer> collect = list.stream().collect(Collectors.toMap(k -> k, v -> v, (k1, k2) -> k1));
System.out.println("collect:" + collect);
}
输出的结果:
{"1:1","2:2","3:3","4:4","5:5","6:6","7:7","8:8"}
toMap()无重复key
示例一
List泛型为 Student 对象,示例需要将name属性作为 key,age 属性作为value;
@Test
public void testList2() {
List<Student> list = Lists.newArrayList(
new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName, Student::getAge));
System.out.println(JSONObject.toJSONString(collect));
}
输出结果:
{"小张":11","小李":5","小王":29"}
示例二
List泛型为 Student 对象,示例需要将name属性作为 key, Student 对象作为value;
@Test
public void testList2() {
List<Student> list = Lists.newArrayList(
new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
Map<String, Student> collect = list.stream().collect(Collectors.toMap(Student::getName, student -> student));
System.out.println(JSONObject.toJSONString(collect));
}
运行结果:
toMap()有重复key
当存在重复 key 时,编译器会报错:java.lang.IllegalStateException: Duplicate key xxxx;
出现这种情况就需要在 toMap() 方法中指定 key 来避免冲突;
示例一
解决办法:使用第一个key 覆盖第二个key;
@Test
public void testList2() {
List<Student> list = Lists.newArrayList(
new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
Map<String, Student> collect = list.stream().collect(Collectors.toMap(Student::getName, student -> student, (key1, key2) -> key1));
System.out.println(JSONObject.toJSONString(collect));
}
运行结果(保留了 “num”:11 的对象):
示例二
解决办法:使用第二个key 覆盖第一个key;
@Test
public void testList2() {
List<Student> list = Lists.newArrayList(
new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
Map<String, Student> collect = list.stream().collect(Collectors.toMap(Student::getName, student -> student, (key1, key2) -> key2));
System.out.println(JSONObject.toJSONString(collect));
}
运行结果(保留了 “num”:2 的对象):
toMap()空指针异常
当 value 为空时,使用 toMap() 方法进行转换,编译器会抛出 java.lang.NullPointerException;
@Test
public void testList2() {
List<Student> list = Lists.newArrayList(
new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
new Student("小田", null, DateUtil.parse("2007-02-21 22:18:56"), null));
Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName, Student::getAge));
System.out.println(JSONObject.toJSONString(collect));
}
运行结果:
解决办法一
转换时增加判断,如果是null,则设置默认值;
@Test
public void testList2() {
List<Student> list = Lists.newArrayList(
new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
new Student("小田", null, DateUtil.parse("2007-02-21 22:18:56"), null));
Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName, s -> s.getAge() == null ? -1 : s.getAge()));
System.out.println(JSONObject.toJSONString(collect));
}
运行结果:
解决办法二
使用 Optional< T > 对值进行包装
(和方式一大同小异,就是换了个写法):
@Test
public void testList2() {
List<Student> list = Lists.newArrayList(
new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
new Student("小田", null, DateUtil.parse("2007-02-21 22:18:56"), null));
Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName, s -> Optional.ofNullable(s.getAge()).orElse(-1)));
System.out.println("Optional:"+JSONObject.toJSONString(collect));
}
运行结果:
解决办法三
使用collect(Supplier< R > supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) 来构建,可允许null值的出现:
@Test
public void testList2() {
List<Student> list = Lists.newArrayList(
new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
new Student(null, 12, DateUtil.parse("2007-02-21 22:18:56"), null));
HashMap<Integer, String> collect = list.stream().collect(HashMap::new, (obj, v) -> obj.put(v.getAge(), v.getName()), HashMap::putAll);
System.out.println("collect:" + collect);
}
运行结果:
List< T > -> Map< T, List< T > >
groupingBy()
直接根据一个字段或者属性分组也可以直接用 groupingBy() 方法:
@Test
public void testList2() {
List<Student> list = Lists.newArrayList(
new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
Map<String, List<Student>> collect = list.stream().collect(Collectors.groupingBy(Student::getName));
System.out.println(JSONObject.toJSONString(collect));
}
运行结果:
partitioningBy()
partitioningBy() 可以理解为特殊的 groupingBy() ,key 值为 Boolean类型:
@Test
public void testList2() {
List<Student> list = Lists.newArrayList(
new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
Map<Boolean, List<Student>> collect = list.stream().collect(Collectors.partitioningBy(s -> s.getNum() >= 5));
System.out.println(JSONObject.toJSONString(collect));
}
运行结果: