JDK1.8之集合的流式操作

一、开场白

1.简介

Stream是JDK1.8之后出现的新特性,也是JDK1.8新特性中最值得学习的两种新特性之一。(另外一个是lambda表达式)
集合的流式操作不是一个数据结构,它并不负责任何数据的存储。非常像一个迭代器。可以有序的获取到数据源中的每一个数据,并且可以对这些数据进行一些操作

2.为什么要使用集合的流式操作

有些时候,对集合中的元素进行操作的时候,需要使用到其他操作的结果。在这个过程中,集合的流式编程可以大幅度的简化代码的数量。将数据源中的数据,读取到一个流中,可以对这个流中的数据进行操作(删除、过滤、映射…)。每次的操作结果也是一个流对象,可以对这个流再进行其他的操作。

3.使用流式编程的步骤

通常情况下,对集合中的数据使用流式编程,需要经过以下三步。
a.获取数据源:集合、数组
b.对数据进行处理的过程: 过滤、排序、映射。。。(中间操作)
c.对流中数据的整合: 转成集合、数量。。。(最终操作)

二、中间操作

1.中间操作1: filter

filter: 是一个过滤器,可以自定义一个过滤条件,将流中满足条件的元素保留
需求: 保留这个集合中成绩>=80的学员信息
Data.getData().stream().filter(ele -> ele.getScore() >= 80).forEach(System.out::println);

2.中间操作2: distinct

distinct: 去重,去除集合中重复的元素
去重规则:先判断hashCode(),如果hashCode相同,再判断equals()
Data.getData().stream().distinct().forEach(System.out::println);

3.中间操作3: sorted

sorted: 排序,对流中的元素进行排序
sorted(): 要求流中的元素对应的类需要实现 Comparable 接口
Data.getData().stream().sorted().forEach(System.out::println);
sorted(Comparator<T> c): 使用自定义的规则来进行排序
Data.getData().stream().sorted((ele1, ele2) -> ele1.getAge() - ele2.getAge()).forEach(System.out::println);

4.中间操作4: limit

limit: 限制,只取流中前指定位的元素
Data.getData().stream().limit(3).forEach(System.out::println);

5.中间操作5: skip

skip: 跳过
Data.getData().stream().skip(3).forEach(System.out::println);
需求: 已知集合中有7个元素,想获取从第2个到第5个元素
Data.getData().stream().skip(1).limit(4).forEach(System.out::println);

6.中间操作6: map

map: 元素映射,用指定的元素来替换掉流中的元素
需求: 将流中的Person对象替换成他们的姓名
Data.getData().stream().map(ele -> ele.getScore() >= 80 ? ele : ele.getName()).forEach(System.out::println);

7.中间操作7: flatMap(注意)

a.什么情况下用到flatMap
当使用map()操作时,不是返回一个值,而是返回一个集合或者一个数组的时候,这时候就可以使用flatMap解决这个问题
b.flatMap如何工作的(使用红色标记的列表和绿色标记的列表,经过flatmap方法后在第二个管道中把把上述两个列表的数据合并成一个列表数据)
c.flatmap 使用例子
String[] array = { "hello", "world" };
需求: 获取所有的字符: List -> h, e, l, l, o, w, o, r, l, d
Arrays.stream(array).map(ele -> ele.split("")).forEach(ele -> System.out.println(ele.length));//输出结果为两个数组
//使用flatMap方法的效果是,将每个数组映射到流的内容,而不是将每个数组映射到一个流,并且合并使用map()时生成的所有单个流
System.out.println(Arrays.stream(array).map(ele -> ele.split("")).flatMap(Arrays::stream).collect(Collectors.toList()));
List<String> lisi1 = Arrays.asList("A", "AA", "AAA");
List<String> lisi2 = Arrays.asList("B", "BB", "BBB");
List<String> lisi3 = Arrays.asList("C", "CC", "CCC");
List<String> lisi4 = Arrays.asList("D", "DD", "DDD");
List<String> lisi5 = Arrays.asList("E", "EE", "EEE");
List<String> lisi6 = Arrays.asList("F", "FF", "FFF");
List<String> lisi7 = Arrays.asList("G", "GG", "GGG");
List<String> lisi8 = Arrays.asList("H", "HH", "HHH");
List<List<String>> listBoss = new ArrayList<>();
listBoss.add(lisi1);
listBoss.add(lisi2);
listBoss.add(lisi3);
listBoss.add(lisi4);
listBoss.add(lisi5);
listBoss.add(lisi6);
listBoss.add(lisi7);
listBoss.add(lisi8);
// 在java8之前
List<String> listOfAll = new ArrayList<>();
for(List<String> person : listBoss){
    for(String name : person){
        listOfAll.add(name);
    }
}
System.out.println(listOfAll);
// java8出现
List<String> flatMapList = listBoss.stream().flatMap(pList -> pList.stream()).collect(Collectors.toList());
System.out.println(flatMapList);

三、最终操作

1.最终操作1: collect

Collectors: 是一个工具类, 提供了若干个方法, 返回一个Collector接口的实现类对象
maxBy: 通过指定的规则, 获取流中最大的元素
System.out.println(Data.getData().stream().collect(Collectors.maxBy((ele1, ele2) -> ele1.getScore() - ele2.getScore())));
minBy: 通过指定的规则, 获取流中最小的元素
System.out.println(Data.getData().stream().collect(Collectors.minBy((ele1, ele2) -> ele1.getAge() - ele2.getAge())));
joining: 合并, 将流中的元素, 以字符串的形式拼接起来
需求: 将集合中所有的Person对象的姓名拼接成一个字符串
String ret1 = Data.getData().stream().map(Person::getName).collect(Collectors.joining());
System.out.println(ret1);
String ret2 = Data.getData().stream().map(Person::getName).collect(Collectors.joining("-"));
System.out.println(ret2);
String ret3 = Data.getData().stream().map(Person::getName).collect(Collectors.joining("-", "{ ", " }"));
System.out.println(ret3);
summingInt: 将流中的元素映射成一个int类型的元素, 最后进行求和
需求: 将集合中的所有的人的成绩求和
System.out.println(Data.getData().stream().collect(Collectors.summingInt(Person::getScore)));
averagingInt: 将流中的元素映射成一个int类型的元素, 最后进行求平均值
System.out.println(Data.getData().stream().collect(Collectors.averagingInt(Person::getScore)));
// summarizingInt : 将流中的元素映射成一个int类型的元素, 最后获取这些数据的描述信息
System.out.println(Data.getData().stream().collect(Collectors.summarizingInt(Person::getScore)));
IntSummaryStatistics ret = Data.getData().stream().collect(Collectors.summarizingInt(Person::getScore));
System.out.println(ret.getCount());
System.out.println(ret.getSum());
System.out.println(ret.getMax());
System.out.println(ret.getMin());
System.out.println(ret.getAverage());
a.转成List
List<Person> list = s.collect(Collectors.toList());
System.out.println(list);
b.转成Set
Set<Person> set = s.collect(Collectors.toSet());
System.out.println(set);
c.转成Map
Map<String, Integer> map = s.collect(Collectors.toMap(Person::getName, Person::getScore));
System.out.println(map);

2.最终操作2: reduce

a.需求1: 求若干个数字的和
Stream<Integer> s1 = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Optional<Integer> ret = s1.reduce((n1, n2) -> n1 + n2);
System.out.println(ret.get());
b.需求2: 求集合中存储的若干Person的成绩和
Person tmp = new Person();
Optional<Person> ret = s.reduce((n1, n2) -> tmp.setScore(n1.getScore() + n2.getScore()));
System.out.println(ret.get().getScore());

3.最终操作3: max 和 min

a.需求1: 找到集合中成绩最高的人的信息
Person max = s.max((ele1, ele2) -> ele1.getScore() - ele2.getScore()).get();
System.out.println(max);
b.需求2: 找到集合中年龄最小的人的信息
Person min = s.min((ele1, ele2) -> ele1.getAge() - ele2.getAge()).get();
System.out.println(min);

4.最终操作4: anyMatch、allMatch、noneMatch

a.需求1: 判断集合中是否包含成绩大于80的学员
boolean ret1 = s.anyMatch(ele -> ele.getScore() > 80);
System.out.println(ret1);
b.需求2: 判断集合中是否所有的学员都及格
boolean ret2 = s.allMatch(ele -> ele.getScore() >= 60);
System.out.println(ret2);
c.需求3: 判断集合中是否所有的学员都及格
boolean ret3 = s.noneMatch(ele -> ele.getScore() <= 60);
System.out.println(ret3);

5.最终操作5: count

需求: 求元数据中有多少个元素
long count = s.count();
System.out.println(count);

6.最终操作6: forEach

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

7.最终操作会关闭一个流,如果一个流被关闭了,再进行其他的操作会抛异常

Person max = s.max((ele1, ele2) -> ele1.getScore() - ele2.getScore()).get();
Person min = s.min((ele1, ele2) -> ele1.getAge() - ele2.getAge()).get();

四、并行流和串行流

// 并行流
long start = System.currentTimeMillis();
//LongStream.rangeClosed(0L, 50000000000L).reduce(Long::sum);
LongStream.rangeClosed(0L, 50000000000L).parallel().reduce(Long::sum);
long end = System.currentTimeMillis();
System.out.println(end - start);
// findFirst: 获取流中的第一个元素, 无论并行流还是串行流
// findAny: 获取流的任意一个元素, 并不是指的随机的元素,对于串行流, 结果等同于findFirst
System.out.println(Data.getData().parallelStream().findFirst());
System.out.println(Data.getData().stream().findFirst());
System.out.println(Data.getData().stream().findAny());
System.out.println(Data.getData().parallelStream().findAny());

五、练习

需求: 一个集合中存储了若干个Person对象(name、age、score),要求查询出以下结果:
// 1. 所有及格的学生信息
List<Person> list = Data.getData().stream().filter(ele -> ele.getScore() >= 60).collect(Collectors.toList()); System.out.println(list);
// 2. 所有及格的学生姓名
List<String> names = Data.getData().stream().filter(ele -> ele.getScore() >= 60).map(ele -> ele.getName()).collect(Collectors.toList());
System.out.println(names);
// 3. 班级的前3名(按照成绩)
List<Person> list2 = Data.getData().stream().sorted((ele1, ele2) -> ele2.getScore() - ele1.getScore()).limit(3).collect(Collectors.toList());
System.out.println(list2);
// 4. 班级的3-10名(按照成绩)
List<Person> list3 = Data.getData().stream().sorted((ele1, ele2) -> ele2.getScore() - ele1.getScore()).skip(2).limit(8).collect(Collectors.toList());
System.out.println(list3);
// 5. 所有不及格的学生平均成绩
Person tmp = new Person();
Data.getData().stream().filter(ele -> ele.getScore() < 60).reduce((ele1, ele2) ->tmp.setScore(ele1.getScore()+ele2.getScore()));
System.out.println(tmp.getScore());
long count = Data.getData().stream().filter(ele -> ele.getScore() < 60).count();
System.out.println(count);
float ave = tmp.getScore() / (float)count;
System.out.println(ave);
// 6. 将及格的学生,按照成绩降序输出所有信息
Data.getData().stream().sorted((ele1, ele2) -> ele2.getScore() - ele1.getScore()).forEach(System.out::println);
//7. 班级学生的总分
Person tmp = new Person();
Data.getData().stream().reduce((ele1, ele2) -> tmp.setScore(ele1.getScore() + ele2.getScore()));
System.out.println(tmp.getScore());
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值