list stream 最大和最小值_Java笔记之Stream详解下篇

本文深入探讨Java Stream API的终止操作,包括查找(如allMatch、anyMatch、noneMatch、findFirst、findAny)、聚合与归约(count、max、min、reduce)、收集操作(collectToList、collectToSet等),并提供了丰富的示例代码,帮助读者掌握Stream API的实用技巧。
摘要由CSDN通过智能技术生成

回顾往期内容

d223be3ee78059472d708e900bd361fd.png

经过上一篇内容的讲解,相信小伙伴们应该或多或少对流基础操作有了那么一丢丢的感觉了吧!当然,streamApi的重要操作其实最主要还是在对流结果的处理上,也就是我们非常关心的终止操作,因为只有经过这一道工序我们才能最终把想要的结果进行进一步收集整理,得到我们最终想要的。所以。接下来呢,让我们进入最重要的一个环节,也就是流的最后一步操作,流的终止操作。

d223be3ee78059472d708e900bd361fd.png

引言

在正式进入前,问小伙伴们一个问题,咱们平常操作数据库,最常用的操作是什么?

相信大家都能答得上来,当然是查询啦。可以说,在增删改查中,查询占比可达到80%以上,这也是为什么数据库的索引会去采用B+树以牺牲增删改性能,来提升查询效率的原因了。既然查询这么重要,当然,stream中也不会缺席,最常用的查询,在Stream当中也都有。接下来,咱们来讲Stream当中关于匹配查找的内容。

cf5c58b1e4dfd3c7c65a1b053346969d.png

首先,我们先给员工类加上个状态

/**
 * @author bihu
 */
public class Employee {

    private String name;

    private Integer age;

    private Double salary;

    private Status status;

    public Employee(String name, Integer age, Double salary, Status status) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.status = status;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return age == employee.age &&
                Double.compare(employee.salary, salary) == 0 &&
                Objects.equals(name, employee.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, salary);
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }

    /**
     * 添加Status内部类
     */
    public enum  Status{
        //空闲
        FREE,
        //忙碌
        BUSY,
        //休假
        VOCATION;
    }

集合申明如下

private static List employees = Arrays.asList(new Employee("张无忌",22,9000.00, Employee.Status.FREE),new Employee("张三丰",88,10000.00, Employee.Status.FREE),new Employee("张翠山",36,8000.00, Employee.Status.VOCATION),new Employee("赵敏",22,7000.00, Employee.Status.FREE),new Employee("谢逊",22,7000.00, Employee.Status.BUSY),new Employee("白眉鹰王",22,7000.00, Employee.Status.BUSY)
    );

1

Stream的查找、聚合、归约

01

Stream中的匹配查找(find )

f867f266b5620fb0ed168eab48584b26.png 1dd76d706adf24d40a82832a19ef9714.png

●allMatch(完全匹配)

检查集合中是否匹配所有元素。

    /**
     * 测试完全匹配
     */
    @Testpublic void testAllMatch(){
        boolean b = employees.stream().allMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b);
    }

输出结果:

3acbb85519f9602a3c9b3d817d92a19d.png

●anyMatch(至少匹配一个)

检查集合中元素至少有一个匹配

    /**
     * 测试至少一个匹配
     */
    @Testpublic void testAnyMatch(){
        boolean b = employees.stream().anyMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b);
    }

输出结果:

43838a724fe81b4f187f808a6370988c.png

●noneMatch(是否没有匹配)

检查集合中是否没有匹配所有元素

    /**
     * 测试检查是否没有匹配的元素
     */
    @Testpublic void testNoneMatch(){
        boolean b = employees.stream().noneMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b);
    }

 输出结果:

620d9428978f93494a5c3a48ebc20c20.png

●findFirst(返回第一个)

返回集合中的第一元素

    /**
     * 返回当前流中的第一个元素
     * 比较工资最低的员工
     */
    @Testpublic void testFindFirst(){
        Optional b = employees.stream()
                .sorted(Comparator.comparingDouble(Employee::getSalary))
                .findFirst();
        System.out.println(b.get());
    }

输出结果:

30864412b3091e16eff42d186c8e46e1.png

●findAny(返回任意一个)

返回集合中任意一个元素,其中可分为单线程和多线程操作,单线程始终返回固定的元素,多线程则返回随机元素

单线程

    /**
     * 单线程
     * 返回当前流中的任意元素
     * 只要有一个是空闲的就从团队里调出来
     */
    @Testpublic void testFindAny1(){
        Optional b = employees.stream()
                .filter((e) -> e.getStatus().equals(Employee.Status.FREE))
                .findAny();
        System.out.println(b.get());
    }

输出结果:

118a0e864363b3a2b185ac00d3dbf9a7.png

多线程

    /**
     * 多线程
     * 返回当前流中的任意元素
     * 只要有一个是空闲的就从团队里调出来
     */
    @Testpublic void testFindAny2(){
        Optional b = employees.parallelStream()
                .filter((e) -> e.getStatus().equals(Employee.Status.FREE))
                .findAny();
        System.out.println(b.get());
    }

 输出结果:

724282e826227b591164f4c3c5fe07f0.png

02

Stream中的简单聚合和归约

f867f266b5620fb0ed168eab48584b26.png b8e14f1bb768e363b06e32afbe77b45f.png

●count(统计集合元素个数)

对集合的元素进行统计,返回统计结果。

    /**
     * 返回当前流中元素的总个数
     */
    @Testpublic void testCount(){
        Long b = employees.stream()
                .count();
        System.out.println(b);

    }

输出结果:

4792109a63c65e7738e79197d0723eaf.png

●max(集合中最大的元素)

统计集合中最大元素,可对员工工资进行比较,返回最大的那个员工对象  

    /**
     * 返回当前流中元素的最大值
     * 找出工资最高的那个人
     */
    @Testpublic void testMax(){
       Optional b = employees.stream()
                .max(Comparator.comparingDouble(Employee::getSalary));
        System.out.println(b.get());
    }

输出结果:

d3836b33e5d54e6c60505ebdd8b63003.png

●min(集合中最小的元素)

与查找最大值相反操作

    /**
     * 返回当前流中元素的最小值
     * 找出工资最低的那个人
     */
    @Testpublic void testMin(){
        Optional min = employees.stream()
                .map(Employee::getSalary)
                .min(Double::compare);
        System.out.println(min.get());
    }

  输出结果:

34b52490ff7374c3f56068a6484a20aa.png

●reduce(归约)

最常用的组合reduce+map它可用于大规模数据集(大于1TB)的并行运算。 


    @Testpublic void testReduce1(){
       List list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer sum = list.stream().reduce(0, (x, y) -> x + y);//其中0为起始值先赋值给x
        System.out.println(sum);
    }

  输出结果:

f1aaf1e0ea6147fbd8e6dbab212c5b95.png

    /**
     * 计算工资的总和是多少
     */
    @Testpublic void testReduce2(){
        Optional reduce = employees.stream()
                .map(Employee::getSalary)
                .reduce(Double::sum);
        System.out.println(reduce.get());
    }

  输出结果:

5d4657b1118b79379800ac3b4d6e815b.png

2

Stream的收集操作

f867f266b5620fb0ed168eab48584b26.png 2f81380169a97746eb59a8abecfe9904.png

● collectToList(收集到List集合)

最常用的list方式收集

    /**
     * 收集到list
     */
    @Test
    public void testCollectList(){
        List list = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());list.forEach(System.out::println);
    }

输出结果:

0c048f5b6880b61e32bdf4227778f9d9.png

● collectToSet(收集到set集合)

可以通过此方式进行去重收集

    /**
     * 收集到set
     */
    @Test
    public void testCollectSet(){
        Set list = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toSet());list.forEach(System.out::println);
    }

添加一条重复数据

e4752016438eb626967382817c6161eb.png

输出结果:

73644ed9ff639444a3a1933400f9bae3.png

● collectToHashSet(到HashSet)

    /**
     * 收集到HashSet
     */
    @Test
    public void testCollectHashSet(){
        HashSet list = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));list.forEach(System.out::println);
    }

输出结果:

8de3197cc2e68324d6ca7ffdd56cd0b4.png

● collectCount(收集count)

    /**
     * 收集count
     */
    @Testpublic void testCollectCounting(){
        Long count = employees.stream()
                .collect(Collectors.counting());
        System.out.println(count);
    }

输出结果:

2e90657e48a4165ed5fe4a3afd1a2296.png

●collectAvgDouble(收集avg)

    /**
     * 收集avg
     */
    @Testpublic void testCollectAvgDouble(){
        Double avg = employees.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(avg);
    }

输出结果:

8fba771d7cda37c3e2e504ee58c3f238.png

● collectSumDouble(收集sum)

    /**
     * 收集sumDouble
     */
    @Testpublic void testCollectSumDouble(){
        Double sum = employees.stream()
                .collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(sum);
    }

输出结果:

0b5ac36ae88e052d3f2c5e0576287a5b.png

● collectMax(收集max)

    /**
     * 收集max
     */
    @Testpublic void testCollectMax(){
        Optional max = employees.stream()
                .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(max.get());
    }

输出结果:

f1b47c90bf493340a91e8733bd6d696e.png

● collectMin(收集min)

    /**
     * 收集min
     */
    @Testpublic void testCollectMin(){
        Optional min = employees.stream()
                .map(Employee::getSalary)
                .collect(Collectors.minBy(Double::compare));
        System.out.println(min.get());
    }

输出结果:

aa14d76d21d319f41c970847206edf6a.png

● collectGroupby(收集分组)

根据员工的状态进行分组

 /**
   * 单条件分组
   */
  @Test
  public void testCollectGroupBy1(){
      MapList> groupByCondition = employees.stream()
            .collect(Collectors.groupingBy(Employee::getStatus));
      System.out.println(groupByCondition);
  }

输出结果:

{VOCATION=[Employee{name='张翠山', age=36, salary=8000.0}], FREE=[Employee{name='张无忌', age=22, salary=9000.0}, Employee{name='张三丰', age=88, salary=10000.0}, Employee{name='赵敏', age=22, salary=7000.0}], BUSY=[Employee{name='谢逊', age=22, salary=7000.0}, Employee{name='白眉鹰王', age=22, salary=7000.0}, Employee{name='白眉鹰王', age=22, salary=7000.0}]}

我们还可以通过多条件分组,先根据状态分组,然后再根据年龄<=35岁一组名为“青年”,年龄<=50的一组名为“中年”,剩下的归位“老年组”。

/**
  * 多条件分组
  */
 @Test
 public void testCollectGroupBy2(){
     MapString, List>> groupByMultiCondition = employees.stream()
          .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(e -> {if (e.getAge() <= 35) {return "青年";
              } else if (e.getAge() <= 50) {return "中年";
              } else {return "老年";
              }
     })));
     System.out.println(groupByMultiCondition);
 }

输出结果:

{FREE={青年=[Employee{name='张无忌', age=22, salary=9000.0}, Employee{name='赵敏', age=22, salary=7000.0}], 老年=[Employee{name='张三丰', age=88, salary=10000.0}]}, BUSY={青年=[Employee{name='谢逊', age=22, salary=7000.0}, Employee{name='白眉鹰王', age=22, salary=7000.0}, Employee{name='白眉鹰王', age=22, salary=7000.0}]}, VOCATION={中年=[Employee{name='张翠山', age=36, salary=8000.0}]}}

● collectPartition(分区收集)

    /**
     * 集合分区
     */
    @Testpublic void testCollectPartition(){
        Map> map = employees.stream()
                .collect(Collectors.partitioningBy(e -> e.getSalary() > 8000));
        System.out.println(map);
    }

可以看到下面会把<=8000分为false一组,>8000分为true一组

输出结果:

{false=[Employee{name='张翠山', age=36, salary=8000.0}, Employee{name='赵敏', age=22, salary=7000.0}, Employee{name='谢逊', age=22, salary=7000.0}, Employee{name='白眉鹰王', age=22, salary=7000.0}, Employee{name='白眉鹰王', age=22, salary=7000.0}], true=[Employee{name='张无忌', age=22, salary=9000.0}, Employee{name='张三丰', age=88, salary=10000.0}]}

● SummaryStatics(汇总收集)

  /**
    * 汇总类
    */
    @Test
    public void testSummaryStatics(){
        DoubleSummaryStatistics dss = employees.stream()
                .collect(Collectors.summarizingDouble(Employee::getSalary));
        System.out.println(dss.getMax());
        System.out.println(dss.getAverage());
        System.out.println(dss.getCount());
        System.out.println(dss.getMin());
        System.out.println(dss.getSum());
    }

可以一次性获取最大值、平均值、统计、最小值、最大值

输出结果:

e56d93567fa99ceb595bae2bbe48ebec.png

● collectJoining(拼接收集)

  /**
     * 字符串拼接
     */
    @Testpublic void testJoining(){
        String str = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.joining(","));
        System.out.println(str);
    }

输出结果:

4f951a9c2a8af1e38ca67494ea036e23.png

aa6cc3310a19e89ea64449752e4f8e4f.png

  完结:

本节小结

关于Stream流到此咱们就已经讲完了,关于JDK1.8之所以越来越被企业认可,首先毋庸置疑是其稳定性,其次,用到1.8自然少不了Lambda表达式和Stream流以及1.8的时间类,关于Stream及Lambda我们只有不断的在业务中使用,才会慢慢的熟能生巧,才能不知不觉的体会其强大之处,希望小伙伴能够勤动手,多思考,突然有一天你会发先原来它是如此简单易用。好了,今天的内容就到这里啦!感谢你的收看。如果觉得对你还有用,就帮忙关注下我的公众号吧!你的支持和赞赏是我创作的不竭动力。

3e3c22d913583160c5e2112ab4dda755.png 3835c1d2d4a4feb463a9c8110a20e6fa.gif

点击关注了解更多精彩内容

扫 码

长按扫描

cf8d923829d1569b66ca10cd0f11487a.png

关 注

关注我

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值