首页 > 其他分享 >Stream流操作

Stream流操作

时间:2023-08-24 18:22:49浏览次数:17  
标签:stream Stream people System Person println 操作 out

1.说明

stream流操作是java8引入的一个新概念,是一种对Java集合运算和表达的高阶抽象。主要是java8用来处理集合的,使我们的代码更简洁高效。
特点:

  • 大大提高编码效率和降低代码的复杂度
  • 不是数据结构,不会保存数据
  • 要有终端操作流才会进行处理,也就是开始流动,如果没有终端操作的话,则流的处理操作不会执行
  • 有串行和并行两种,但是并行的时候处理的数组是无序的,所以一般对排序没有要求的时候才会使用并行

2.分类

流操作主要分为中间操作和终端操作两大类,其中中间操作又分为无状态和有状态两小类,终端操作又分为非短路操作和短路操作。

  • 无状态:指元素的处理不受之前元素的影响
  • 有状态:指该操作只有拿到之前的元素之后才能继续下去
  • 非短路操作:指必须处理所有的元素才能得到结果
  • 短路操作:指遇到一些符合/不符合条件的元素就可以获取结果,不一定非要处理完所有的元素

分类树状图:
image

3.使用

3.1 流的创建

stream流的创建大致有五种创建方法:
(1).使用Collection下的 stream() 和 parallelStream() 方法
其中stream()就是创建一个普通的流,而parallelStream()则是一个并行的流,另外也可以通过Stream的parallel()方法将普通的流改变为并行的流。

List<Person> people = Person.initPerson();
Stream<Person> stream = people.stream();
Stream<Person> parallelStream = people.parallelStream();

(2).使用Arrays 中的 stream() 方法,将数组转成流

Integer[] age = {12, 13, 14, 15, 16, 17, 18};
Stream<Integer> ageStream = Arrays.stream(age);

(3).使用Stream中的静态方法:of()、iterate()、generate()

Stream<Integer> ofStream = Stream.of(12, 13, 14, 15, 16, 17, 18);
ofStream.forEach(System.out::println);
Stream<Integer> iterateStream = Stream.iterate(2, s -> s * (s - 1) + 1).limit(6);
iterateStream.forEach(System.out::println);
Stream<Double> generateStream = Stream.generate(Math::random).limit(6);
generateStream.forEach(System.out::println);

运行结果:
image
(4).使用 BufferedReader.lines() 方法,将每行内容转成流

BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\admin\\Desktop\\123.sql"));
// 这里直接将流通过collect()转化为了List
List<String> collect = reader.lines().collect(Collectors.toList());
collect.forEach(System.out::println);

运行结果:
image
(5).使用 Pattern.splitAsStream() 方法,将字符串分隔成流

Pattern pattern = Pattern.compile(",");
List<String> collect = pattern.splitAsStream("a,b,c,d").collect(Collectors.toList());
collect.forEach(System.out::println);

运行结果:
image

3.2 中间操作的使用

例子中用到的Person类为:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {

    private String name;
    private Integer age;
    private Double score;

    public static List<Person> initPerson() {
        return Arrays.asList(new Person("张三", 14, 80.0),
                new Person("李四", 15, 70.0),
                new Person("王二", 16, 80.0),
                new Person("麻子", 15, 80.0),
                new Person("张三", 14, 80.0));
    }

    @Override
    public String toString() {
        return "name:" + name + ",age:" + age + ",score:" + score;
    }

    @Override
    public boolean equals(Object a) {
        return hashCode() == a.hashCode();
    }

    @Override
    public int hashCode() {
        return toString().hashCode();
    }

}

(1)filter中间操作
filter中间操作是过滤操作,筛选出一些符合条件的数据。样例:

List<Person> people = Person.initPerson();
long count = people.stream().filter(person -> person.getAge().equals(14)).count();
System.out.println(count);

运行结果:
image
从上面的结果可以看出,其筛选出了两个age为14的数据。
(2)map中间操作
map中间操作是对数据进行映射,处理,相关的扩展还有mapToInt,mapToLong,mapToDouble这三个操作会降数据分别转化为int,long,double。样例:

List<Person> people = Person.initPerson();
List<String> collect = people.stream().map(Person::toString).collect(Collectors.toList());
collect.forEach(System.out::println);
people.stream().mapToInt(u -> u.toString().length()).forEach(System.out::println);
people.stream().mapToLong(Person::getAge).forEach(System.out::println);
people.stream().mapToDouble(Person::getAge).forEach(System.out::println);

运行结果:
image
(3)flatMap中间操作
flatMap中间操作和map中间操作一样,不过区别是flatMap操作的返回类型只能为Stream流,也就是从一个流转化为另一个流。
(4)peek中间操作
peek中间操作是传递一个消费性函数接口作为参数对数据及逆行消费。样例:

List<Person> people = Person.initPerson();
people.stream().peek(s -> {
    if (s.getAge() > 15)
        s.setAge(17);
}).forEach(System.out::println);
System.out.println("----------------------------------------------------------");
System.out.println(people);

运行结果:
image
(5)unorder中间操作
unorder中间操作,消除相遇顺序,主要用于并行流,提高并行流的性能,因为并行流在处理有序数据结构时,对性能会有很大的影响。
PS:不过这边进行样例的时候发现好像加了unorder的比没加unorder的用时还要旧,不确定是不是因为数据太少。增加数据之后进行测试,发现增加unorder的用时变化不大,而没加unorder的用时增加了些。

List<Person> people = Person.initPerson();
long time = new Date().getTime();
people.stream().parallel().unordered().map(Person::getAge).forEach(System.out::println);
System.out.println("******************************************************");
people.stream().parallel().unordered().map(Person::getAge).forEach(System.out::println);
long time1 = new Date().getTime();
System.out.println(time1 - time);
System.out.println("******************************************************");
long time2 = new Date().getTime();
people.stream().parallel().map(Person::getAge).forEach(System.out::println);
System.out.println("******************************************************");
people.stream().parallel().map(Person::getAge).forEach(System.out::println);
long time3 = new Date().getTime();
System.out.println(time3 - time2);

运行结果:
image
(6)distinct中间操作
distinct中间操作通过流中元素的 hashCode() 和 equals() 去除重复元素,样例:

List<Person> people = Person.initPerson();
people.forEach(System.out::println);
System.out.println("------------------------------------------------------");
// distinct中间操作,进行去重操作
people.stream().distinct().forEach(System.out::println);

运行结果:
image
(7)sorted中间操作
sorted中间操作是一个排序操作,能够进行定制排序和自然排序,定制排序就是传一个比较器参数。样例:

List<Person> people = Person.initPerson();
people.stream().sorted(Comparator.comparing(s1 -> s1.getAge(), (a1,a2) -> a2 - a1)).forEach(System.out::println);
System.out.println("------------------------------------------------------");
people.stream().sorted(Comparator.comparing(Person::getAge).thenComparing(Person::getScore).reversed()).forEach(System.out::println);

运行结果:
image
(8)limit中间操作
limit中间操作就是获取n个元素,就像是sql中的limit。样例:

List<Person> people = Person.initPerson();
people.stream().limit(1).forEach(System.out::println);

运行结果:
image
(9)skip中间操作
skip中间操作是跳过n个元素,与limit相互配合时可以实现分页功能。样例:

List<Person> people = Person.initPerson();
people.stream().skip(2).forEach(System.out::println);
System.out.println("------------------------------------------------------");
people.stream().skip(2).limit(2).forEach(System.out::println);

运行结果:
image

3.3 终端操作

(1)anyMatch终端操作
anyMatch终端操作是进行判断是否有数据满足条件,只要有一条数据满足条件就会返回true。样例:

List<Person> people = Person.initPerson();
System.out.println(people.stream().map(Person::getAge).anyMatch(s1 -> s1 > 15));
System.out.println(people.stream().map(Person::getAge).anyMatch(s1 -> s1 > 17));

运行结果:
image
(2)allMatch终端操作
allMatch终端操作是判断数据是否满足条件,必须全部的数据满足条件才会返回true,只要有一个不满足条件就会返回false。样例:

List<Person> people = Person.initPerson();
System.out.println(people.stream().map(Person::getAge).allMatch(s1 -> s1 > 15));
System.out.println(people.stream().map(Person::getAge).allMatch(s1 -> s1 > 13));

运行结果:
image
(3)noneMatch终端操作
noneMatch终端操作时判断数据是否全部不满足条件,只有全部不满足条件才会返回true,否则返回false。样例:

List<Person> people = Person.initPerson();
System.out.println(people.stream().map(Person::getAge).noneMatch(s1 -> s1 > 16));
System.out.println(people.stream().map(Person::getAge).noneMatch(s1 -> s1 > 15));

运行结果:
image
(4)findFirst终端操作
findFirst终端操作是返回第一个满足条件的数据。样例:

List<Person> people = Person.initPerson();
System.out.println(people.stream().parallel().filter(s1 -> s1.getAge() > 14).findFirst());

运行结果:
image
(5)findAny终端操作
findAny终端操作时返回任意一个满足条件的数据,不一定是第一个。样例:

List<Person> people = Person.initPerson();
System.out.println(people.stream().parallel().filter(s1 -> s1.getAge() > 14).findAny());

运行结果:
image
(6)forEach终端操作
foreach终端操作时对数据进行遍历消费,说白了就是一个循环操作。样例:

List<Person> people = Person.initPerson();
people.stream().parallel().forEach(System.out::println);

运行结果:
image
(7)forEachOrdered终端操作
forEachOrdered终端操作也是一个循环,不过与forEach终端操作不同的是forEachOrdered能保证循环是按照顺序进行循环的。样例:

List<Person> people = Person.initPerson();
people.stream().parallel().forEachOrdered(System.out::println);

运行结果:
image
(8)toArray终端操作
toArray终端操作是将流转化为数组的操作,如果不写参数则转化为object数组,写参数则转为当前所写参数的数组。样例:

List<Person> people = Person.initPerson();
Object[] objects = people.stream().toArray();
for (Object object : objects) {
    System.out.println(object);
}
System.out.println("------------------------------------------------------");
Person[] persons = people.stream().toArray(Person[]::new);
for (Person person : persons) {
    System.out.println(person);
}

运行结果:
image
(9)min终端操作
min终端操作是获取数据中的最小值,返回值是Optional。样例:

List<Person> people = Person.initPerson();
Optional<Person> min = people.stream().min(Comparator.comparing(Person::getAge));
System.out.println(min);

运行结果:
image
(10)max终端操作
max终端操作是获取数据中的最大值,返回值也是Optional。样例:

List<Person> people = Person.initPerson();
Optional<Person> max = people.stream().max(Comparator.comparing(Person::getAge));
System.out.println(max);

运行结果:
image
(11)count终端操作
count终端操作是获取流中的数据量。样例:

List<Person> people = Person.initPerson();
System.out.println(people.stream().count());

运行结果:
image
(12)reduce终端操作
reduct终端操作是根据指定的计算模型将Stream中的值计算得到一个最终结果,其分为一个参数,两个参数和三个参数的方法。一个参数:就是进行计算的逻辑,两个参数:一个初始值,一个计算逻辑,三个参数:也是一个初始值,一个计算逻辑,一个合并逻辑,合并逻辑只会针对并发时冲突的情况。样例:

List<Person> people = Person.initPerson();
// 获取所有数据年龄的和
Integer sum = people.stream().map(Person::getAge).reduce((s1, s2) -> s1 + s2).get();
System.out.println(sum);
// 获取所有数据的年龄的和,并其初始值为10
Integer sum1 = people.stream().map(Person::getAge).reduce(10, (s1, s2) -> s1 + s2);
System.out.println(sum1);

// 计算所有年龄的和,初始值为0,如果冲突的话则取其中最大的,当发生冲突时求的就不是和了
Integer sum2 = people.stream().map(Person::getAge).reduce(0, (s1, s2) -> s1 + s2, (s1, s2) -> s1 > s2 ? s1 : s2);
System.out.println(sum2);

运行结果:
image
(13)collect终端操作
collect终端操作是收集操作,可以说是对处理过后的流进行一些归纳处理。其收集器有多种,具体如下:

收集器 功能描述
toList 转化为list集合
toSet 转化为set集合
toColection 转化为collection集合
toMap 转化为map
counting 计算数量
summingInt 计算和,根据值得类型有不同的派生,比如summingLong等
averagingInt 计算平均值,根据值的类型不同也会有不同的派生,比如averagingLong等
joining 根据字符串进行拼接流中的元素
maxBy 根据比较器选择出值最大的元素
minBy 根据比较器选择出值最小的元素
groupingBy 按照给定的分组函数进行分组,返回值类型为map
partitioningBy 根据给定的分区函数的值进行分区,会将key分为true和false的map
collectingAndThen 对流的结果进行二次加工转换
reducing 从给定的初始值逐一处理,知道最后只剩一个结果为止,和reduce终端操作类似

各种收集器的样例:

List<Person> people = Person.initPerson();
// toList收集器,转为list数组
List<Person> collect = people.stream().collect(Collectors.toList());
System.out.println(collect);
// toSet收集器,转为set集合
Set<Person> collect1 = people.stream().collect(Collectors.toSet());
System.out.println(collect1);
// toCollection收集器,转为collection集合
List<Person> collect2 = people.stream().collect(Collectors.toCollection(ArrayList<Person>::new));
System.out.println(collect2);
// toMap收集器,转为map
Map<String, Person> collect3 = people.stream().collect(Collectors.toMap(Person::getName, Function.identity(), (s1, s2) -> s2));
System.out.println(collect3);
// counting收集器,计算数量
Long collect4 = people.stream().collect(Collectors.counting());
System.out.println(collect4);
// summingInt收集器,计算和,根据值的类型不同有不同的派生,比如summingLong等
Integer collect5 = people.stream().collect(Collectors.summingInt(Person::getAge));
System.out.println(collect5);
// averagingInt收集器,计算平均值,根据值的类型不同也会有不同的派生,比如averagingLong
Double collect6 = people.stream().collect(Collectors.averagingInt(Person::getAge));
System.out.println(collect6);
// joining收集器,进行拼接流中的元素
String collect7 = people.stream().map(Person::toString).collect(Collectors.joining("||"));
System.out.println(collect7);
// maxBy收集器,根据比较器选择出值最大的元素
Person person = people.stream().collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge())).get();
System.out.println(person);
// minBy收集器,根据比较器选择出值最小的元素
Person person1 = people.stream().collect(Collectors.minBy((s1, s2) -> s1.getAge() - s2.getAge())).get();
System.out.println(person1);
// groupingBy收集器,按照给定的分组函数进行分组
Map<String, List<Person>> collect8 = people.stream().collect(Collectors.groupingBy(Person::getName));
System.out.println(collect8);
// partitioningBy收集器,根据给定的分区函数的值进行分区,会将key分为true和false两个map
Map<Boolean, List<Person>> collect9 = people.stream().collect(Collectors.partitioningBy(s -> s.getAge() > 15));
System.out.println(collect9);
// collectingAndThen收集器,对其结果进行二次加工转换
List<Person> collect10 = people.stream().collect(Collectors.collectingAndThen(Collectors.partitioningBy(s -> s.getAge() > 15), sm -> sm.get(true)));
System.out.println(collect10);
// reducing收集器,从给定的初始值逐一处理,直到最后只剩一个结果位置,和reduce终端操作类似
Integer collect11 = people.stream().map(Person::getAge).collect(Collectors.reducing(10, (s1, s2) -> s1 + s2));
System.out.println(collect11);

运行结果:
image

标签:stream,Stream,people,System,Person,println,操作,out
From: https://www.cnblogs.com/mcj123/p/17645559.html

相关文章

  • Stream流将list装换为map
    首先定义的userList内容如下:[User(id=1,name=第一人,telephone=第一手机号,address=第一住址),User(id=2,name=第二人,telephone=第二手机号,address=第二住址),User(id=1,name=第三人,telephone=第三手机号,address=第三住址),User(id=1,name=第四人,telephone=第......
  • 【图像处理】图像处理常用操作
    去除背景色参考文章:Python3,4行代码实现去除图片背景色,从此告别PS!!_python去除图片背景色_Carl_奕然的博客-CSDN博客在线抠图软件_图片去除背景|remove.bg–remove.bg修改图像尺寸参考文章:如何缩小图片,降低图片kb-知乎(zhihu.com)对于纯无底色的白色图片,用画图工具res......
  • 多线程|加锁操作
    classCounter{publicintcount=0;publicvoidadd(){count++;}}publicclasssynDemo{publicstaticvoidmain(String[]args){Countercounter=newCounter();Threadt1=newThread(()->{for(inti=......
  • FAST协议详解2 操作符
    一、概述操作符是FAST进行数据压缩的法宝之一,比如一个递增的数字,如果通过传统方式传输(比如二进制)则每一次都需要传递一个完整的数字,而使用递增操作符后,则不需要再传递这个字段,接收方根据模版里的操作符属性,自动将该字段的值+1即可。 二、操作符类型看接口文档,存在以下类型的......
  • 【知识整理】基于Springboot的Kafka消费者动态操作
    基于Springboot的Kafka消费者动态操作1.问题​ 在基于Springboot开发Kafka相关业务时,遇到如下业务场景:执行部分操作时,如停止服务替换镜像、执行特殊业务处理等,需要先停止Consumer接收Kafka消息,待处理完成后再开启Consumer接续接收Kafka消息为并发消费Kafka消息,可通过配置sp......
  • 【Python】pandas操作, 取最大值, 最小值, 平均值, 生成 空值, 多个 series合并, 替换
    1.取最大值,最小值,平均值df.max()df.iloc[:,1:].max()df.min()df.mean()#输出indexvalue2.生成空值,带index的seriespd.Series(index=['1','2','3'],dtype='object')"""1NaN2NaN3NaNdtype:objec......
  • 量子相关计算基本操作2
    几种电路恒等式举例:以下电路的作用是否相同? 由于所以第一个电路可以等价于(1)同时,由于  所以(1)电路可转化为 故二者等价。电路化简规则 举例:  ......
  • adocker yml如何操作才能让搭建的redis集群能通过外网访问ip+端口的集群所有信息
    要在Docker中操作以便通过外部网络访问Redis集群的IP和端口,您需要执行以下操作:首先,您需要创建一个DockerComposeYAML文件(docker-compose.yml),用于定义Redis集群的配置。在此文件中,您可以指定每个Redis节点的配置和网络设置。以下是一个示例配置:version:'3'services:redis1:......
  • Nginx内置lua版OpenResty拦截转发请求Redis等操作
    Nginx内置lua版OpenResty拦截转发请求Redis等操作1下载并安装OpenRestyhttp://openresty.org/cn/download.html2下载lua-resty-http-0.17.1库以让openresty的lua支持外部http访问能力lua-resty-http-0.17.11下载lua-resty-http-0.17.12然后将文件中lua-resty-http......
  • windows 桌面GUI自动化- 12.pywinauto 组合框控件ComboBox操作
    前言pywinauto组合框控件ComboBox操作场景记事本-另存为-编码选择,下图这种就是组合框控件ComboBoxselect选择官网给的教程是通过select选择选项示例frompywinautoimportApplicationapp=Application('uia').start("notepad.exe")win=app.window(title_re="......