Java8 Stream 用法大全

文章目录

  • 前言
  • 一、Stream 特性
  • 二、Stream 创建
    • 2.1 用集合创建流
    • 2.2 用数组创建流
    • 2.3 Stream静态方法
  • 三、Stream 使用案例
    • 3.1 遍历 forEach
    • 3.2 过滤 filter
    • 3.3 查找 findFirst,findAny
    • 3.4 匹配 match
    • 3.5 映射 map
    • 3.6 截取流 limit
    • 3.7 排序 sorted
    • 3.8 去重 distinct
    • 3.9 统计 summaryStatistics
    • 3.10 归约 reduce
    • 3.11 归集 toList,toSet,toMap
    • 3.12 分组 partitioningBy,groupingBy
    • 3.13 合并 joining

前言

Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本。 Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等。
新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。它可以让你以一种声明的方式处理数据,从而写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

一、Stream 特性

  1. 元素是特定类型的对象,形成一个队列。 Java中的Stream不会存储元素,而是按需计算按照特定的规则对数据进行计算,一般会输出结果。
  2. Stream不会改变数据源,一般情况下会产生一个新的集合或者新值。
  3. Stream流的来源,可以是集合,数组,I/O channel, 产生器generator 等等。
  4. Stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。
  5. 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

Stream流的操作可以大概分为2种:

  1. 中间操作:每次操作都返回流对象本身。
  2. 终端操作:一个流只可以进行一次终端操作,即产生一个新的集合或者新值。终端操作结束后流无法再次使用。

二、Stream 创建

在 Java 8 中, Stream可以由集合或数组创建而来,生成的流有2种类型:

stream() :串行流,由主线程按顺序对流执行操作。parallelStream() :并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。例如计算集合中的数量之和。如果流种数据量很大,并行流可以加快处理速度。串行流可以通过parallel()方法把顺序流转换成并行流。

2.1 用集合创建流
因为集合继承或实现了java.util.Collection接口,而Collection接口定义了stream()和parallelStream()方法,所以可通过集合的stream() 和parallelStream()方法创建流。

2.2 用数组创建流
使用java.util.Arrays.stream(T[] array)方法用数组创建流。

2.3 Stream静态方法
使用Stream的静态方法生成Stream,例如of()、iterate()、generate()等。

以下所有案例会基于学生数据,学生类,以及测试数据如下:

package com.nobody;

/**
* @Description 学生类
* @Author Mr.nobody
* @Date 2021/1/17
* @Version 1.0
*/
public class Student {
// 主键
private String id;
// 姓名
private String name;
// 年龄
private int age;
// 性别
private String sex;
// 成绩
private double score;

public Student(String id, String name, int age, String sex, double score) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.score = score;
}
// 省略get和set方法,toString方法,如若测试需自行添加
12345678910111213141516171819202122232425262728
List<Student> students = new ArrayList<>(16);
students.add(new Student("1", "张三", 18, "male", 88));
students.add(new Student("2", "李四", 17, "male", 60));
students.add(new Student("3", "王五", 18, "male", 100));
students.add(new Student("4", "赵六", 20, "male", 10));
students.add(new Student("5", "董七", 14, "female", 95));
students.add(new Student("6", "幺八", 21, "male", 55));
students.add(new Student("7", "老九", 20, "female", 66));
students.add(new Student("8", "小明", 18, "male", 100));
students.add(new Student("9", "小红", 22, "female", 95));
students.add(new Student("10", "小张", 25, "male", 90));
1234567891011

3.1 遍历 forEach

students.stream().forEach(System.out::println);

// 输出结果
Student{id='1', name='张三', age=18, sex=male, score=88.0}
Student{id='2', name='李四', age=17, sex=male, score=60.0}
Student{id='3', name='王五', age=18, sex=male, score=100.0}
Student{id='4', name='赵六', age=20, sex=male, score=10.0}
Student{id='5', name='董七', age=14, sex=female, score=95.0}
Student{id='6', name='幺八', age=21, sex=male, score=55.0}
Student{id='7', name='老九', age=20, sex=female, score=66.0}
Student{id='8', name='小明', age=18, sex=male, score=100.0}
Student{id='9', name='小红', age=22, sex=female, score=95.0}
Student{id='10', name='小张', age=25, sex=male, score=90.0}
12345678910111213

3.2 过滤 filter

// 过滤出成绩100分的学生
List<Student> students1 =
students.stream().filter(student -> student.getScore() == 100).collect(Collectors.toList());
students1.forEach(System.out::println);

// 输出结果
Student{id='3', name='王五', age=18, sex=male, score=100.0}
Student{id='8', name='小明', age=18, sex=male, score=100.0}
12345678

3.3 查找 findFirst,findAny

一般filter和find搭配使用,即从过滤符合条件的数据中,获得一个数据。

// 串行流,匹配第一个
Optional<Student> studentOptional =
students.stream().filter(student -> student.getAge() >= 20).findFirst();
if (studentOptional.isPresent()) {
Student student = studentOptional.get();
System.out.println(student);
}
// 上面输出语句可简写如下
// studentOptional.ifPresent(System.out::println);

// 并行流,匹配任意一个,findAny一般用于并行流
Optional<Student> studentOptiona2 =
students.parallelStream().filter(student -> student.getAge() >= 20).findAny();
studentOptiona2.ifPresent(System.out::println);

// 输出结果
Student{id='4', name='赵六', age=20, sex=male, score=10.0}
Student{id='7', name='老九', age=20, sex=female, score=66.0}
123456789101112131415161718

3.4 匹配 match

// 是否存在100分的学生
boolean anyMatch = students.stream().anyMatch(student -> student.getScore() == 100);
// 是否全部学生都100分
boolean allMatch = students.stream().allMatch(student -> student.getScore() == 100);
// 是否全部学生都没有100分
boolean noneMatch = students.stream().noneMatch(student -> student.getScore() == 100);
System.out.println(anyMatch);
System.out.println(allMatch);
System.out.println(noneMatch);

// 输出结果
true
false
false
1234567891011121314

3.5 映射 map

映射,顾名思义,将一个对象映射成另外一个对象。即一个Stream流中的所有元素按照一定的映射规则,映射到另一个流中。映射有map和flatMap两种类型:
map:接收一个函数作为参数,此函数作用到Stream中每一个元素,形成一个新的元素,所有新的元素组成一个新的流。
flatMap:接收一个函数作为参数,它将流中的每个元素都转换成另一个流,然后把所有流再连接形成一个最终流。

// 获取每个学生的姓名
List<String> studentNames =
students.stream().map(Student::getName).collect(Collectors.toList());
System.out.println(studentNames);
// 每个学生的成绩加10分
List<Double> studentScores = students.stream().map(student -> student.getScore() + 10)
.collect(Collectors.toList());
System.out.println(studentScores);

// 输出结果
[张三, 李四, 王五, 赵六, 董七, 幺八, 老九, 小明, 小红, 小张]
[98.0, 70.0, 110.0, 20.0, 105.0, 65.0, 76.0, 110.0, 105.0, 100.0]
123456789101112

List<String> list = Arrays.asList("a-b-c-d", "g-h-i");
List<String> list1 = list.stream().flatMap(s -> Arrays.stream(s.split("-"))).collect(Collectors.toList());
System.out.println(list1);

// 输出结果
[a, b, c, d, g, h, i]
123456

3.6 截取流 limit

// limit方法用于获取指定数量的流。例如下面演示取出学习成绩大于70的5个人
List<Student> students2 = students.stream().filter(student -> student.getScore() > 70)
.limit(5).collect(Collectors.toList());
students2.forEach(System.out::println);
// 跳过第一个再取2个
List<Student> students8 = students.stream().skip(1).limit(2).collect(Collectors.toList());
// 获取5个int随机数,按从小到大排序
Random random = new Random();
random.ints().limit(5).sorted().forEach(System.out::println);

// 输出结果
Student{id='1', name='张三', age=18, sex=male, score=88.0}
Student{id='3', name='王五', age=18, sex=male, score=100.0}
Student{id='5', name='董七', age=14, sex=female, score=95.0}
Student{id='8', name='小明', age=18, sex=male, score=100.0}
Student{id='9', name='小红', age=22, sex=female, score=95.0}
-1490202714
145340547
368332155
388399398
1099579920
123456789101112131415161718192021

3.7 排序 sorted

sorted 方法用于对流中的元素进行排序,有两种排序:
sorted():自然排序,流中元素需要实现Comparable接口。
sorted(Comparator<? super T> comparator):需要自定义排序器。

// 按成绩升序
List<Student> students3 = students.stream().sorted(Comparator.comparing(Student::getScore))
.collect(Collectors.toList());
System.out.println("按成绩升序");
students3.forEach(System.out::println);
// 按成绩降序
List<Student> students4 =
students.stream().sorted(Comparator.comparing(Student::getScore).reversed())
.collect(Collectors.toList());
System.out.println("按成绩降序");
students4.forEach(System.out::println);
// 按成绩升序,再按年龄升序
List<Student> students5 = students.stream()
.sorted(Comparator.comparing(Student::getScore).thenComparing(Student::getAge))
.collect(Collectors.toList());
System.out.println("按成绩升序,再按年龄升序");
students5.forEach(System.out::println);
// 按成绩升序,再按年龄降序
List<Student> students6 = students.stream().sorted((s1, s2) -> {
if (s1.getScore() != s2.getScore()) {
return (int) (s1.getScore() - s2.getScore());
} else {
return (s2.getAge() - s1.getAge());
}
}).collect(Collectors.toList());
System.out.println("按成绩升序,再按年龄降序");
students6.forEach(System.out::println);
123456789101112131415161718192021222324252627

3.8 去重 distinct

List<String> list2 = Arrays.asList("a", "b", "a", "c", "f", "e", "f");
List<String> list3 = list2.stream().distinct().collect(Collectors.toList());
Set<String> stringSet = list2.stream().collect(Collectors.toSet()); // list转set也可以达到去重效果
System.out.println(list3);
System.out.println(stringSet);

// 输出结果
[a, b, c, f, e]
[a, b, c, e, f]
123456789

3.9 统计 summaryStatistics

一些收集器能产生统计结果,例如Collectors提供了一系列用于数据统计的静态方法,它们主要用于int、double、long等基本类型上。

// 总和统计summaryStatistics
DoubleSummaryStatistics doubleSummaryStatistics =
students.stream().mapToDouble(Student::getScore).summaryStatistics();
System.out.println("平均值:" + doubleSummaryStatistics.getAverage());
System.out.println("总个数:" + doubleSummaryStatistics.getCount());
System.out.println("最大值:" + doubleSummaryStatistics.getMax());
System.out.println("最小值:" + doubleSummaryStatistics.getMin());
System.out.println("总和值:" + doubleSummaryStatistics.getSum());

// 输出结果
平均值:75.9
总个数:10
最大值:100.0
最小值:10.0
总和值:759.0
123456789101112131415

// 统计张三出现的次数

long conts = students.stream().filter(s -> StringUtils.equals(s.getName(), "张三")).count();

// 统计个数
long count = students.stream().count();
// 平均值
Double averageScore =
students.stream().collect(Collectors.averagingDouble(Student::getScore));
// 最大值和最小值
Optional<Double> maxScore = students.stream().map(Student::getScore).max(Double::compare);
Optional<Double> minScore = students.stream().map(Student::getScore).min(Double::compare);
// 求和
double sumScore = students.stream().mapToDouble(Student::getScore).sum();
// 一次性统计所有
DoubleSummaryStatistics doubleSummaryStatistics1 =
students.stream().collect(Collectors.summarizingDouble(Student::getScore));
System.out.println("单个维度计算:");
System.out.println("统计个数:" + count);
System.out.println("平均值:" + averageScore);
maxScore.ifPresent(aDouble -> System.out.println("最大值:" + aDouble));
minScore.ifPresent(aDouble -> System.out.println("最小值:" + aDouble));
System.out.println("求和:" + sumScore);
System.out.println("一次性统计所有:" + doubleSummaryStatistics1);

//////////////////////////////////////////////

List<Long> remainderRaffleNum = new ArrayList<>(); // 求和

Long totalValue = remainderRaffleNum.stream().mapToLong(Long::longValue).sum();

longList.stream().mapToLong(Long::longValue).max();
longList.stream().mapToLong(Long::longValue).min();

/////////////////////////////////////////////////

// 输出结果
单个维度计算:
统计个数:10
平均值:75.9
最大值:100.0
最小值:10.0
求和:759.0
12345678910111213141516171819202122232425262728

3.10 归约 reduce

归约,把一个流归约(缩减)成一个值,能实现对集合求和、求乘积和求最值等操作。

List<Integer> integerList = Arrays.asList(6, 7, 1, 10, 11, 7, 13, 20);
// 求和
Optional<Integer> sum1 = integerList.stream().reduce(Integer::sum);
// 求和,基于10的基础上
Integer sum2 = integerList.stream().reduce(10, Integer::sum);
// 求最大值
Optional<Integer> max1 = integerList.stream().reduce((x, y) -> x > y ? x : y);
// 求最大值,基于与50比较的基础上
Integer max2 = integerList.stream().reduce(50, Integer::max);
Optional<Integer> min = integerList.stream().reduce(Integer::min);
// 求乘积
Optional<Integer> product = integerList.stream().reduce((x, y) -> x * y);
System.out.println("原始集合:" + integerList);
System.out.println("集合求和:" + sum1.get() + "," + sum2);
System.out.println("集合求最大值:" + max1.get() + "," + max2);
System.out.println("集合求最小值:" + min.get());
System.out.println("集合求积:" + product.get());

// 输出结果
原始集合:[6, 7, 1, 10, 11, 7, 13, 20]
集合求和:75,85
集合求最大值:20,50
集合求最小值:1
集合求积:8408400
123456789101112131415161718192021222324

3.11 归集 toList,toSet,toMap

Java中的Stream不会存储元素,而是按需计算按照特定的规则对数据进行计算,一般会输出结果。所以流中的数据完成处理后,需要将流中的数据重新归集到新的集合里。比较常用的是toList、toSet和toMap,以及复杂的toCollection、toConcurrentMap等。

// 获取学生名字,形成新的list集合
List<String> studentNames1 =
students.stream().map(Student::getName).collect(Collectors.toList());
// 获取年龄大于等于15的年龄set集合
Set<Integer> ageSet = students.stream().filter(student -> student.getAge() >= 15)
.map(Student::getAge).collect(Collectors.toSet());
// 创建学生ID和学生实体的map
Map<String, Student> studentMap =
students.stream().collect(Collectors.toMap(Student::getId, student -> student));
System.out.println(studentNames1);
System.out.println(ageSet);
studentMap.forEach((key, value) -> System.out.println(key + ":" + value));

// 输出结果
[张三, 李四, 王五, 赵六, 董七, 幺八, 老九, 小明, 小红, 小张]
[17, 18, 20, 21, 22, 25]
1:Student{id='1', name='张三', age=18, sex=male, score=88.0}
2:Student{id='2', name='李四', age=17, sex=male, score=60.0}
3:Student{id='3', name='王五', age=18, sex=male, score=100.0}
4:Student{id='4', name='赵六', age=20, sex=male, score=10.0}
5:Student{id='5', name='董七', age=14, sex=female, score=95.0}
6:Student{id='6', name='幺八', age=21, sex=male, score=55.0}
7:Student{id='7', name='老九', age=20, sex=female, score=66.0}
8:Student{id='8', name='小明', age=18, sex=male, score=100.0}
9:Student{id='9', name='小红', age=22, sex=female, score=95.0}
10:Student{id='10', name='小张', age=25, sex=male, score=90.0}
1234567891011121314151617181920212223242526

3.12 分组 partitioningBy,groupingBy

Map<String, List<SmsCustomerSendDetail>> collect = details.stream().collect(Collectors.groupingBy(SmsCustomerSendDetail::getCustomerId));

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

partitioningBy(分区):stream中的元素按条件被分为两个Map。
groupingBy(分组):stream中的元素按条件被分为多个Map。

// 按条件学生成绩是否大于等于60,划分为2个组
Map<Boolean, List<Student>> studentScorePart = students.stream()
.collect(Collectors.partitioningBy(student -> student.getScore() >= 60));
// 按性别分组
Map<String, List<Student>> studentSexMap =
students.stream().collect(Collectors.groupingBy(Student::getSex));
// 按年龄分组
Map<Integer, List<Student>> studentAgeMap =
students.stream().collect(Collectors.groupingBy(Student::getAge));
// 先按性别分组,再按年龄分组
Map<String, Map<Integer, List<Student>>> collect = students.stream().collect(
Collectors.groupingBy(Student::getSex, Collectors.groupingBy(Student::getAge)));
System.out.println("按条件学生成绩是否大于等于60,划分为2个组:");
studentScorePart.forEach((aBoolean, students7) -> {
System.out.println("成绩大于等于60?:" + aBoolean);
students7.forEach(System.out::println);
});
System.out.println("按性别分组:");
studentSexMap.forEach((sex, students7) -> {
System.out.println("性别?:" + sex);
students7.forEach(System.out::println);
});
System.out.println("按年龄分组:");
studentAgeMap.forEach((age, students7) -> {
System.out.println("年龄:" + age);
students7.forEach(System.out::println);
});
System.out.println("先按性别分组,再按年龄分组:");
collect.forEach((sex, integerListMap) -> {
System.out.println("性别:" + sex);
integerListMap.forEach((age, students7) -> {
System.out.println("年龄:" + age);
students7.forEach(System.out::println);
});
});

//输出结果
按条件学生成绩是否大于等于60,划分为2个组:
成绩大于等于60?:false
Student{id='4', name='赵六', age=20, sex=male, score=10.0}
Student{id='6', name='幺八', age=21, sex=male, score=55.0}
成绩大于等于60?:true
Student{id='1', name='张三', age=18, sex=male, score=88.0}
Student{id='2', name='李四', age=17, sex=male, score=60.0}
Student{id='3', name='王五', age=18, sex=male, score=100.0}
Student{id='5', name='董七', age=14, sex=female, score=95.0}
Student{id='7', name='老九', age=20, sex=female, score=66.0}
Student{id='8', name='小明', age=18, sex=male, score=100.0}
Student{id='9', name='小红', age=22, sex=female, score=95.0}
Student{id='10', name='小张', age=25, sex=male, score=90.0}
按性别分组:
性别?:female
Student{id='5', name='董七', age=14, sex=female, score=95.0}
Student{id='7', name='老九', age=20, sex=female, score=66.0}
Student{id='9', name='小红', age=22, sex=female, score=95.0}
性别?:male
Student{id='1', name='张三', age=18, sex=male, score=88.0}
Student{id='2', name='李四', age=17, sex=male, score=60.0}
Student{id='3', name='王五', age=18, sex=male, score=100.0}
Student{id='4', name='赵六', age=20, sex=male, score=10.0}
Student{id='6', name='幺八', age=21, sex=male, score=55.0}
Student{id='8', name='小明', age=18, sex=male, score=100.0}
Student{id='10', name='小张', age=25, sex=male, score=90.0}
按年龄分组:
年龄:17
Student{id='2', name='李四', age=17, sex=male, score=60.0}
年龄:18
Student{id='1', name='张三', age=18, sex=male, score=88.0}
Student{id='3', name='王五', age=18, sex=male, score=100.0}
Student{id='8', name='小明', age=18, sex=male, score=100.0}
年龄:20
Student{id='4', name='赵六', age=20, sex=male, score=10.0}
Student{id='7', name='老九', age=20, sex=female, score=66.0}
年龄:21
Student{id='6', name='幺八', age=21, sex=male, score=55.0}
年龄:22
Student{id='9', name='小红', age=22, sex=female, score=95.0}
年龄:25
Student{id='10', name='小张', age=25, sex=male, score=90.0}
年龄:14
Student{id='5', name='董七', age=14, sex=female, score=95.0}
先按性别分组,再按年龄分组:
性别:female
年龄:20
Student{id='7', name='老九', age=20, sex=female, score=66.0}
年龄:22
Student{id='9', name='小红', age=22, sex=female, score=95.0}
年龄:14
Student{id='5', name='董七', age=14, sex=female, score=95.0}
性别:male
年龄:17
Student{id='2', name='李四', age=17, sex=male, score=60.0}
年龄:18
Student{id='1', name='张三', age=18, sex=male, score=88.0}
Student{id='3', name='王五', age=18, sex=male, score=100.0}
Student{id='8', name='小明', age=18, sex=male, score=100.0}
年龄:20
Student{id='4', name='赵六', age=20, sex=male, score=10.0}
年龄:21
Student{id='6', name='幺八', age=21, sex=male, score=55.0}
年龄:25
Student{id='10', name='小张', age=25, sex=male, score=90.0}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102

 //====================================================

 // 

按照一个属性分组
Map<String, List<TestHA>> collect = list.stream().collect(Collectors.groupingBy(TestHA::getNumbers));
for (String s :collect.keySet()) {
System.out.println("----"+collect.get(s));
}
// 按照多个属性分组
Map<String, List<TestHA>> collect1 = list.stream().collect(Collectors.groupingBy(x -> x.getNumbers() + x.getName() + x.getId()) );
for (String s :collect1.keySet()) {
System.err.println("======"+collect1.get(s));
}

结果:

----[TestHA(id=12, name=张三, numbers=111), TestHA(id=1, name=张三, numbers=111)]
[TestHA(id=1, name=张三, numbers=222)]


=====[TestHA(id=1, name=张三, numbers=111)]
[TestHA(id=1, name=张三, numbers=222)]
[TestHA(id=12, name=张三, numbers=111)]

//=====================

public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Mxy");
list.add("StringUtils");
list.add("join");
String join = String.join("-",list);//传入String类型的List集合,使用"-"号拼接
System.out.println("=========only-qi========"+join);

// Mxy-StringUtils-join
String[] s = new String[]{"Yuan","Mxy"};//传入String类型的数组,使用"-"号拼接
String join2 = String.join("-",s);
System.out.println("=========only-qi========"+join2);

// "=========only-qi========Mxy-StringUtils-join
}

 

 

3.13 合并 joining

将stream中的元素用指定的连接符(没有的话,则直接连接)连接成一个字符串。

String joinName = students.stream().map(Student::getName).collect(Collectors.joining(", "));
System.out.println(joinName);

// 输出结果
张三, 李四, 王五, 赵六, 董七, 幺八, 老九, 小明, 小红, 小张


12345

 

//===================================================================================================================================================================================================

构造list集合

List<Map<String,Object>> list = Lists.newArrayList();

IntStream.range(1,5).forEach(e->{

    Map<String,Object> map = Maps.newHashMap(); map.put("name","张三"+(e<3?e:e-1)); map.put("score", (int)(Math.random()*100)+1); list.add(map);

});

System.out.println(list);

输出:[{score=60, name=张三1}, {score=94, name=张三2}, {score=75, name=张三2}, {score=55, name=张三3}]

 

根据map中的score进行过滤

//过滤分数大于60的元素

List<Map<String, Object>> filterList = list.stream().filter( e -> (int) e.get("score") > 60).collect(Collectors.toList());

System.out.println(filterList);

输出:[{score=94, name=张三2}, {score=75, name=张三2}]

根据map中的score进行排序

List<Map<String, Object>> sortList = list.stream().sorted((v1, v2) -> {

    BigInteger b1 = new BigInteger(v1.get("score").toString());

    BigInteger b2 = new BigInteger(v2.get("score").toString());

     return b1.compareTo(b2); }).collect(Collectors.toList());

System.out.println(sortList);

输出:[{score=55, name=张三3}, {score=60, name=张三1}, {score=75, name=张三2}, {score=94, name=张三2}]

对集合中的map的value值求和

//通过Collect方式

int score = list.stream().collect(Collectors.summingInt( e -> Integer.parseInt(e.get("score").toString())));

//通过map方式

int sum = list.stream().mapToInt(e -> Integer.parseInt(e.get("score").toString())).sum();

System.out.println(sum);

根据map的name进行分组,并将name相同的score值求和

List<Map<String, Object>> collectList = list.stream().collect(

      Collectors.groupingBy(e -> e.get("name"))).values().stream().map(e ->

       { Map<String, Object> map = e.get(0); map.put("score", e.stream().map( s ->

      new BigInteger(s.get("score").toString())).reduce(BigInteger.ZERO, BigInteger::add)); return map; }).collect(Collectors.toList());

System.out.println(collectList);

输出:[{score=55, name=张三3}, {score=60, name=张三1}, {score=169, name=张三2}]

List<Map<String,Object>> 去重

//构建数据
List<Map<String,Object>> list1 = new ArrayList<>();
     
Map<String,Object> map = new HashMap();
Map<String,Object> map2 = new HashMap();

map.put("key","1");
map.put("value","a");
map2.put("key","2");
map2.put("value","a");

list1.add(map2);
list1.add(map);
	       
list1.forEach(System.out::println);   //打印数据

List<Map<String, Object>> list2 = list1.stream().collect(
	               Collectors.collectingAndThen(
	                       Collectors.toCollection(
	                       () ->new TreeSet<>(Comparator.comparing(m->m.get("value").toString()))
	                       ),ArrayList::new
	               )
	       );    //根据value字段值去重,保留第一次放入list的map值
System.out.println("--------");
list2.forEach(System.out::println);

//结果打印:
//{value=a, key=2}
//{value=a, key=1}
//--------
//{value=a, key=2}

更改List<Map<String,Object>> 里面Map对象的值

List<Map<String, Object>> list1 = new ArrayList<>();

Map<String, Object> map = new HashMap();
Map<String, Object> map2 = new HashMap();

map.put("key", "1");
map.put("value", "a");
map2.put("key", "2");
map2.put("value", "a");

list1.add(map2);
list1.add(map);

list1.forEach(System.out::println);

//将Map里面的每一个对象的key改为aaaa
List<Map<String, Object>> list2 = list1.stream().map(x -> {
			x.put("key", "aaaa");
			return x;
		}).collect(Collectors.toList());
System.out.println("--------");
list2.forEach(System.out::println);		


//{value=a, key=2}
//{value=a, key=1}
//--------
//{value=a, key=aaaa}
//{value=a, key=aaaa}
 

 

posted on 2021-01-25 15:20  UnmatchedSelf  阅读(740)  评论(0编辑  收藏  举报

导航