栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

10分钟了解stream流的N种玩法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

10分钟了解stream流的N种玩法

stream流是java8里的新特性,最近整理了一下stream相关的知识,现在分享给大家。

终端操作是指:该流已经无法继续使用只能创建一个新的流在继续操作。
中间操作指:后面可以继续进行其他对流的操作。

创建流的方式非常简单
最常见的,你可以通过对集合和数组的转化,创建流。

  List list=new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        final Stream stream = list.stream();

你还可以通过切割字符串(返回string数组)创建

String str = "1,2,3,4,54,56,45,5,4";
final Stream stream1 = Arrays.stream(str.split(","));

废话不多说马上就开始实战演练。
这是等会会用到的类,set和get方法可以自己创建或者使用@data注解也行

class Person {
    private String name;  // 姓名
    private int salary; // 薪资
    private int age; // 年龄
    private String sex; //性别
    private String area;  // 地区

    // 构造方法
    public Person(String name, int salary, int age,String sex,String area) {
        this.name = name;
        this.salary = salary;
        this.age = age;
        this.sex = sex;
        this.area = area;
    }}

放在main方法中:

  List personList = new ArrayList();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 24, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 34, "female", "Washington"));
        personList.add(new Person("Anni", 8200, 32, "female", "New York"));
        personList.add(new Person("Owen", 9500, 25, "male", "New York"));
        personList.add(new Person("Alisa", 7900, 26, "female", "New York"));
filter和foreach方法。

这里使用了lambda表达式,对人员对象的工资进行了过滤,然后foreach循环输出人员的name:

 personList.stream().filter(x -> x.getSalary() > 7900)
 .forEach(x -> System.out.println(x.getName()));

在这里普及一下 : lambda表达式 这里的x代表流中经过的一个元素 ->符号后的就是筛选的条件 filter方法会自动过滤 并只留下符合条件的元素。

findFirst()方法

这里同样是筛选
与filter方法不同的地方在于 他会返回第一个符合条件的对象,但是可能为空所以为Optional类型
这里的orElse方法是为了当返回为空是new一个空的对象给他;

    Person person1 = personList.parallelStream()
    .filter(x -> x.getSalary() > 8000)
    .findFirst().orElse(new Person());
     System.out.println(person1.getName());
 
map方法 map方法是最常用且功能最强大的stream方法

map方法可以在方法里面用另一个方法对流中的元素进行映射
这里的.map(Person::getName) 是对元素进行剥离 也就是对元素进行getname方法 取出元素的name 形成一个新的流。
collect(Collectors.toSet()) 是对新的流组成一个集合。

Set collect = personList
.stream().filter(x -> x.getSalary() > 8000)
.map(Person::getName)
.collect(Collectors.toSet());


map对元素进行方法映射 取出映射后的流 比如 将大写字符转成小写

   List collect1 = personList.stream()
   .map(Person::getArea)
   .map(String::toLowerCase)
   .collect(Collectors.toList());
System.out.println("collect1 = " + collect1);

这里依然是使用map对流进行映射 将所有元素的工资都加300 不过有一点要注意使用了 map(Person::getSalary) 后 新的流是salary组成的新流

List collect2 = personList.stream().map(Person::getSalary)
.map(x -> x + 300).collect(Collectors.toList());
System.out.println("collect2 = " + collect2);


我甚至可以这样
StreamTest::personAdd 这种 ::的写法可以调用 非静态方法 应该是因为省略的对象调用的写法

 List collect3 = personList.stream()
 .map(StreamTest::personAdd).collect(Collectors.toList());

personAdd方法是我写在main函数外的方法 调用外部函数对stram流中的元素进行映射

   public static Person personAdd(Person person) {
        person.setSalary(person.getSalary() + 500);
        return person;
    }
}

你也可以在map中对对象进行重组

 Stream> 
 mapStream = personList.stream().map(x -> {
            Map map = new HashMap<>();
            map.put(x.getName(), x);
            return map;
        });

flatmap方法
flatmap方法的作用是将n个流从头到尾串起来 类似为stringbuffer的 append方法

String[] strings = {"a,o,a,q,w,e,e,e", "w,u,u,y,y,t,t,r,r,u"};
 Arrays.stream(strings).flatMap(x -> {
Stream stream = Arrays.stream(x.split(","));
 return stream;
 }).forEach(System.out::println);

max方法
取出流中的元素的最大值

       Optional max = personList.stream()
       .map(Person::getAge)
       .max(Comparator.comparing(Integer::byteValue));
        System.out.println("max = " + max);
  Optional max1 = personList.stream()
  .max(Comparator.comparingInt(Person::getSalary));
 System.out.println("max1.get() = " + max1.get().getSalary());

count方法
将结果集进行聚合 统计条数

long count = personList.stream()
.filter(x -> x.getSalary() > 8000).count();
System.out.println("count = " + count);

reduce方法 :在该方法里同时对流中两个的元素进行重复操作
十分难用
我感觉很鸡肋
规约方法:就是对流里的所有数据进行一个聚合 比如统计 求最大 累乘 啥的
最终缩减成一个值

Integer integer = personList.stream().map(Person::getSalary).reduce((x, y) -> x + y).orElse(-1);
System.out.println(integer);

Integer integer1 = personList.stream().map(Person::getAge).reduce(0, Integer::max);
System.out.println("integer1 = " + integer1);

Integer reduce = personList.stream().reduce(1, (x, p) -> x *= p.getSalary(), Integer::sum);
System.out.println(reduce);


收集(collect)方法
对流中的元素进行各种花式操作
在流中的数据完成处理后,需要将流中的数据重新归集到新的集合里。toList、toSet和toMap比较常用,另外还有toCollection、toConcurrentMap等复杂一些的用法。
Collectors提供了一系列用于数据统计的静态方法:

计数:count
平均值:averagingInt、averagingLong、averagingDouble
最值:maxBy、minBy
求和:summingInt、summingLong、summingDouble
统计以上所有:summarizingInt、summarizingLong、summarizingDouble

personList.stream().filter(x -> x.getSalary() > 8000).collect(Collectors.toMap(Person::getName, Person::getSalary)).forEach((s, integer2) -> System.out.println(s + "    " + integer2));
        Long collect4 = personList.stream().collect(Collectors.counting());
        System.out.println("collect4 = " + collect4);
        
        Double collect5 = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
        System.out.println("collect5 = " + collect5);
        
        DoubleSummaryStatistics collect6 = personList.stream().collect(Collectors.summarizingDouble(Person::getAge));
        System.out.println("collect6 = " + collect6);
        
        Integer collect7 = personList.stream().collect(Collectors.summingInt(Person::getAge));
        System.out.println("collect7 = " + collect7);


分组(partitioningBy/groupingBy)
分区:将stream按条件分为两个Map,比如员工按薪资是否高于8000分为两部分。
分组:将集合分为多个Map,比如员工按性别分组。有单级分组和多级分组。

Map> collect8 = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
        collect8.forEach((x, y) -> {

            System.out.println(x);
            for (Person person :
                    y) {
                System.out.println("person = " + person.getName() + "   " + person.getSalary());
            }
        });

      Map> collect9 = personList.stream().collect(Collectors.groupingBy(Person::getSex));
        collect9.forEach((x, y) -> {
            System.out.println(x);
            for (Person person :
                    y) {
                System.out.println("person = " + person.getName() + "   " + person.getSalary());
            }
        });

Map>> collect10 = personList.stream().collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy(Person::getArea)));
        collect10.forEach((x, y) -> {
            System.out.println(x);
            y.forEach((z, u) -> {
                System.out.println(z);
                for (Person p :
                        u) {
                    System.out.println("p.getName()+"  "+p.getArea()+"  "+p.getArea() = " + p.getName() + "  " + p.getArea() + "  " + p.getArea());

                }
            });
        });

学到这里是不是已经累了,但是我想说不要放弃 就快结束了!!!

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

String collect11 = personList.stream()
.map(Person::getName)
.collect(Collectors.joining("-", "{", "}"));
System.out.println(collect11);

   String collect12 = personList.stream().map(x -> {
            return String.valueOf(x.getAge());
        }).collect(Collectors.joining(",", "{", "}"));
        System.out.println(collect12);

sored方法
排序

personList.stream()
.sorted(Comparator.comparingInt(Person::getAge))
.forEach(person -> System.out.println(person.getAge()));
 
 personList.stream().
 sorted(Comparator.comparing(Person::getName).thenComparing(Person::getAge))
 .forEach(person 
 -> System.out.println("  name   " + person.getName() + " age  " + person.getAge()));


最后就是
contcat方法 合并流
limit方法 截取前几位的元素
skip方法 跳过某些元素

String s = "abcdeaaa";
        String s1 = "12345112";
        Stream stream = Arrays.stream(s.split(""));
        Stream stream1 = Arrays.stream(s1.split(""));
        String collect13 = Stream.concat(stream, stream1).distinct().collect(Collectors.joining("-", "{", "}"));
        System.out.println("collect13 = " + collect13);
        Stream.concat(Arrays.stream(s.split("")), Arrays.stream(s1.split(""))).skip(2).limit(6).forEach(System.out::println);

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/999280.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号