ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

lamdba03 Java8新特性之四:Stream API

2021-04-26 13:58:02  阅读:215  来源: 互联网

标签:stream Stream Person System personList API 之四 println out


Java8新特性之四:Stream API


Java8的两个重大改变,一个是Lambda表达式,另一个就是Stream API表达式。 Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找、过滤、筛选等操作,在新版的JPA【连接数据库】中,也已经加入了Stream。
Stream API给我们操作集合带来了强大的功用,同时Stream API操作简单,容易上手。

例如

@Query("select u from User u")
Stream<User> findAllByCustomQueryAndStream();

Stream<User> readAllByFirstnameNotNull();

@Query("select u from User u")
Stream<User> streamAllPaged(Pageable pageable);

Stream的操作步骤

Stream有如下三个操作步骤:

一、创建Stream
从一个数据源,如集合、数组中获取流。
二、中间操作
一个操作的中间链,对数据源的数据进行操作。
三、终止操作
一个终止操作,执行中间操作链,并产生结果。
注意:对流的操作完成后需要进行关

举个简单的例子:

假设有一个Person类和一个Person列表,现在有两个需求:1)找到年龄大于18岁的人并输出;2)找出所有中国人的数量。

@Data
class Person {
    private String name;
    private Integer age;
    private String country;
    private char sex;

    public Person(String name, Integer age, String country, char sex) {
        this.name = name;
        this.age = age;
        this.country = country;
        this.sex = sex;
    }
}
List<Person> personList = new ArrayList<>();
personList.add(new Person("欧阳雪",18,"中国",'F'));
personList.add(new Person("Tom",24,"美国",'M'));
personList.add(new Person("Harley",22,"英国",'F'));
personList.add(new Person("向天笑",20,"中国",'M'));
personList.add(new Person("李康",22,"中国",'M'));
personList.add(new Person("小梅",20,"中国",'F'));
personList.add(new Person("何雪",21,"中国",'F'));
personList.add(new Person("李康",22,"中国",'M'));

在JDK8以前,我们可以通过遍历列表来完成。但是在有了Stream API后,可以这样来实现:

 public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("欧阳雪", 18, "中国", 'F'));
        personList.add(new Person("Tom", 24, "美国", 'M'));
        personList.add(new Person("Harley", 22, "英国", 'F'));
        personList.add(new Person("向天笑", 20, "中国", 'M'));
        personList.add(new Person("李康", 22, "中国", 'M'));
        personList.add(new Person("小梅", 20, "中国", 'F'));
        personList.add(new Person("何雪", 21, "中国", 'F'));
        personList.add(new Person("李康", 22, "中国", 'M'));


//    1)找到年龄大于18岁的人并输出;
//创建stream对象      boolean test(T t);      void accept(T t);
        personList.stream().filter(t->t.getAge()>20).forEach(t->System.out.println(t));
//        lamdba 里面的方法引用
personList.stream().filter(t->t.getAge()>20).forEach(System.out::println);

//    2)找出所有中国人的数量。  count()计算数量
    long c = personList.stream().filter(t -> t.getCountry().equals("中国")).count();

        System.out.println(c);
    }

在这个例子中,personList.stream()是创建流,filter()属于中间操作,forEach、count()是终止操作。

Stream中间操作–筛选与切片 与parallelStream并行流

filter:接收Landba,从流中排除某些操作
limit:截断流,使其元素不超过给定对象
skip(n):跳过元素,返回一个扔掉了前n个元素的流,若流中不足n个,则返回一个空流,与limit(n)互补
distinct:筛选,通过流所生成元素的hashCode()和equals()去除重复元素。

limit举例

需求,从Person列表中取出两个女性。

//        从Person列表中取出两个女性。 limit
      personList.stream().filter(t -> t.getSex() == 'F').limit(2).forEach(System.out::println);

skip举例

从Person列表中从第2个女性开始,取出所有的女性。

//        从Person列表中从第2个女性开始,取出所有的女性。  skip(1)表示跳过第一个
        personList.stream().filter(t->t.getSex()=='F').skip(1).forEach(System.out::println);

distinct举例

//        去重
        personList.stream().distinct().forEach(System.out::println);

Stream中间操作–映射

  • map–接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  • flatMap–接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

map举例

比如,我们用一个PersonCountry类来接收所有的国家信息

//        比如,我们用一个PersonCountry类来接收所有的国家信息       R apply(T t);
        personList.stream().map(t->t.getCountry()).forEach(System.out::println);

接收所有的姓名和国家 首先封装一个两个字段的实体类

//      接收所有的姓名和国家  首先封装一个两个字段的实体类
        personList.stream().map(t->new NameAndCountry(t.getName(),t.getCountry())).forEach(System.out::println);
@Data
@AllArgsConstructor
@NoArgsConstructor
class  NameAndCountry{
    private String name;
    private String country;
}

对前面的personList按照年龄从小到大排序,年龄相同,再按照姓名排序

//对前面的personList按照年龄从小到大排序,年龄相同,再按照姓名排序
//使用无参必须该类实现自然排序
//        personList.stream().sorted();
//           int compare(T o1, T o2);
//        第一种方法
        personList.stream().sorted((o1, o2) -> {
            if (o1.getAge() == o2.getAge()) {
                return o1.getName().compareTo(o2.getName());
            }
            return o1.getAge() - o2.getAge();
        }).forEach(System.out::println);
        System.out.println("-----------------");
//第二种方法 使用三目运算符
        personList.stream().sorted((o1, o2) ->o1.getAge()==o2.getAge()?o1.getName().compareTo(o2.getName()):o1.getAge()-o2.getAge()).forEach(System.out::println);

总结

1. filter(Predicate)
2. limit(long)
3. skip(long)
4. distinct();
5. map(Function)
6. sorted()  | sorted(Comparator)

终止操作–查找与匹配

  • allMatch–检查是否匹配所有元素
  • anyMatch–检查是否至少匹配一个元素
  • noneMatch–检查是否没有匹配所有元素
  • findFirst–返回第一个元素
  • findAny–返回当前流中的任意元素
  • count–返回流中元素的总个数
  • max–返回流中最大值
  • min–返回流中最小值

这些方面在Stream类中都有说明,这里不一一举例,只对allMatch、max各举一例进行说明。

allMatch检查是否至少匹配一个元素

判断personList中的人是否都是大于18岁的

//检查是否至少匹配一个元素
        boolean b = personList.stream().anyMatch(item -> item.getAge() >18);
        System.out.println(b);

判断personList中的人是否都是成年人

//        判断personList中的人是否都是中国人:
        boolean b1 = personList.stream().allMatch(p -> p.getCountry().equals("中国"));
        System.out.println(b1);

findAny返回当前流中的任意元素

在这里插入图片描述

//返回当前流中的任意元素
        Optional<Person> any = personList.stream().findAny();
        System.out.println(any);
//返回当前流中的任意元素
//        Person person = personList.stream().findAny().get();
        Person person = personList.parallelStream().findAny().get();
        System.out.println(person);

max-返回流中最大值

personList中找到年龄最大的

//        找到年龄最大的      int compare(T o1, T o2);
        Optional<Person> max = personList.stream().max((o1, o2) -> o1.getAge() - o2.getAge());
        System.out.println(max);

归约

Stream API的归约操作可以将流中元素反复结合起来,得到一个值,有

Optional<T> reduce(BinaryOperator<T> accumulator);

T reduce(T identity, BinaryOperator<T> accumulator);

<U> U reduce(U identity,
                 BiFunction<U, ? super T, U> accumulator,
                 BinaryOperator<U> combiner);

求一个1到100的和

第一种方法:
用到了reduce第二个方法:T reduce(T identity, BinaryOperator accumulator)

        //        求1-100的和  规约
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(new Random().nextInt(10));
        }
        System.out.println(list);
//    R apply(T t, T u,T r);
        Optional<Integer> reduce = list.stream().reduce((t, u) -> t + u);
        System.out.println(reduce);

把这个动作拆解一下,其运算步骤模拟如下:
0 (1,2) -> 1 + 2 + 0
3 (3,4) -> 3 + 4 + 3
10 (5,6) -> 5 + 6 + 10
其运算步骤是,每次将列表的两个元素相加,并将结果与前一次的两个元素的相加结果进行累加,因此,在开始时,将identity设为0,因为第1个元素和第2个元素在相加的时候,前面还没有元素操作过
第二种方法:

     Integer[] list = {1, 2, 3, 4, 5};
        System.out.println(Arrays.asList(list));

        Arrays.stream(list).reduce((t,u)->{
            System.out.println(t+"-----"+u);
            return t+u;
        });
        System.out.println(Arrays.asList(list));

求所有人的年龄之和

//        求所有人的年龄之和
        Optional<Integer> reduce = personList.stream().map(item -> item.getAge()).reduce((t, u) -> t + u);
        System.out.println(reduce);

求所有人的平均年龄

Collectors.averagingDouble

//averagingDouble
        Double collect1 = personList.stream().collect(Collectors.averagingDouble(t -> t.getAge()));
        System.out.println(collect1);

求所有人的年龄的集合

collect(Collectors.toList())

        List<Integer> collect = personList.stream().map(item -> item.getAge()).collect(Collectors.toList());

在这里插入图片描述

求集合中所有人的最大年龄

//        求出集合中最大年龄
        Optional<Person> collect2 = personList.stream().collect(Collectors.maxBy((o1, o2) -> o1.getAge() - o2.getAge()));
        System.out.println(collect2);

最小年龄类型。
还有其他很操作,可以参考java.util.stream.Collectors。

注意流的关闭

求集合中所有人的最小年龄。

 try(final Stream<Integer> integerStream = personList.stream().map(Person::getAge)) {
   final Optional<Integer> minAge = integerStream.collect(Collectors.minBy(Integer::compareTo));
   System.out.println(minAge.get());
}

最好将流的操作放到try-with-resources,本章前面内容为了方便,没有放到try-with-resources中。

完整测试代码

package com.zz.lamdab.lamdba04;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

public class Deom1 {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("欧阳雪", 18, "中国", 'F'));
        personList.add(new Person("Tom", 24, "美国", 'M'));
        personList.add(new Person("Harley", 22, "英国", 'F'));
        personList.add(new Person("向天笑", 20, "中国", 'M'));
        personList.add(new Person("李康", 22, "中国", 'M'));
        personList.add(new Person("小梅", 20, "中国", 'F'));
        personList.add(new Person("何雪", 21, "中国", 'F'));
        personList.add(new Person("李康", 22, "中国", 'M'));


//    1)找到年龄大于18岁的人并输出;
//创建stream对象      boolean test(T t);      void accept(T t);
        personList.stream().filter(t -> t.getAge() > 20).forEach(t -> System.out.println(t));
//        lamdba 里面的方法引用
        personList.stream().filter(t -> t.getAge() > 20).forEach(System.out::println);

//    2)找出所有中国人的数量。  count()计算数量
        long c = personList.stream().filter(t -> t.getCountry().equals("中国")).count();

        System.out.println(c);

//        从Person列表中取出两个女性。 limit
        personList.stream().filter(t -> t.getSex() == 'F').limit(2).forEach(System.out::println);

//        从Person列表中从第2个女性开始,取出所有的女性。  skip(1)表示跳过第一个
        personList.stream().filter(t -> t.getSex() == 'F').skip(1).forEach(System.out::println);
        System.out.println("-----------------");
//        去重
        personList.stream().distinct().forEach(System.out::println);
        System.out.println("-----------------");

//        比如,我们用一个PersonCountry类来接收所有的国家信息       R apply(T t);
        personList.stream().map(t -> t.getCountry()).forEach(System.out::println);
//      接收所有的姓名和国家  首先封装一个两个字段的实体类
        personList.stream().map(t -> new NameAndCountry(t.getName(), t.getCountry())).forEach(System.out::println);

        System.out.println("-----------------");
//对前面的personList按照年龄从小到大排序,年龄相同,再按照姓名排序
//使用无参必须该类实现自然排序
//        personList.stream().sorted();
//           int compare(T o1, T o2);
//        第一种方法
        personList.stream().sorted((o1, o2) -> {
            if (o1.getAge() == o2.getAge()) {
                return o1.getName().compareTo(o2.getName());
            }
            return o1.getAge() - o2.getAge();
        }).forEach(System.out::println);
        System.out.println("-----------------");
//第二种方法 使用三目运算符
        personList.stream().sorted((o1, o2) ->o1.getAge()==o2.getAge()?o1.getName().compareTo(o2.getName()):o1.getAge()-o2.getAge()).forEach(System.out::println);
        System.out.println("-----------------");
//返回当前流中的任意元素
        Optional<Person> any = personList.stream().findAny();
        System.out.println(any);
        System.out.println("-----------------");
//        检查是否至少匹配一个元素
        boolean b = personList.stream().anyMatch(item -> item.getAge() >18);
        System.out.println(b);
//        判断personList中的人是否都是中国人:
        boolean b1 = personList.stream().allMatch(p -> p.getCountry().equals("中国"));
        System.out.println(b1);
//返回当前流中的任意元素
//        Person person = personList.stream().findAny().get();
        Person person = personList.parallelStream().findAny().get();
        System.out.println(person);

//        找到年龄最大的      int compare(T o1, T o2);
        Optional<Person> max = personList.stream().max((o1, o2) -> o1.getAge() - o2.getAge());
        System.out.println(max);



//        求所有人的年龄之和
        Optional<Integer> reduce = personList.stream().map(item -> item.getAge()).reduce((t, u) -> t + u);
        System.out.println(reduce);

        List<Integer> collect = personList.stream().map(item -> item.getAge()).collect(Collectors.toList());
//averagingDouble
        Double collect1 = personList.stream().collect(Collectors.averagingDouble(t -> t.getAge()));
        System.out.println(collect);
        System.out.println(collect1);
//        求出集合中最大年龄
        Optional<Person> collect2 = personList.stream().collect(Collectors.maxBy((o1, o2) -> o1.getAge() - o2.getAge()));
        System.out.println(collect2);
//        注意流的关闭
//        Stream<Integer> integerStream = personList.stream().map(Person::getAge);


        try(final Stream<Integer> integerStream = personList.stream().map(Person::getAge)) {
            final Optional<Integer> minAge = integerStream.collect(Collectors.minBy(Integer::compareTo));
            System.out.println(minAge.get());

        }

    }


}

@Data
class Person {
    private String name;
    private Integer age;
    private String country;
    private char sex;

    public Person(String name, Integer age, String country, char sex) {
        this.name = name;
        this.age = age;
        this.country = country;
        this.sex = sex;
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class NameAndCountry {
    private String name;
    private String country;
}

标签:stream,Stream,Person,System,personList,API,之四,println,out
来源: https://blog.csdn.net/weixin_45861581/article/details/116145039

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有