Stream流的方法很多?基本上都在这里了

细说 Stream 中的用法

大概了解了 Stream流 的一个过程后,让我们来一起当回厂长,去 "流水线" 中的每一个生产车间去检验检验,瞅瞅这个 "流水线" 都能干些什么?

说实话,当这个图弄上来的时候,我都不知道该从哪个先开始...

既然前面 Stream流 初体验 中用到了去重,那么就先从 distinct() 这个先开始吧!

先来搭一些 "前期准备" 吧...

  1. 基础类

    @Data
    @AllArgsConstructor
    public class Book {
    	// 书籍名称
        private String bookName;
    	// 作者
        private String author;
    	// 作者的年龄
        private Integer age;
    	// 书的价格
        private Integer price;
    }
    复制代码

    我这里用的是 Lombok 中的 @Data 里面包含了:Getter、Setter、RequiredArgsConstructor、ToString、EqualsAndHashCode

  2. 公用的集合 (内容自己定义吧,不重要... 整几个相同的就行)

        @Test
        public List<Book> getBooks(){
            List<Book> books = new ArrayList<>();
            Collections.addAll(books,
                    new Book("笑傲江湖", "金庸", 99, 365),
                    new Book("笑傲江湖", "金庸", 99, 365),
                    new Book("神雕侠侣", "金庸", 99, 365),
                    new Book("雪中悍刀行","烽火戏诸侯",35,320),
                    new Book("雪中悍刀行","烽火戏诸侯",35,320),
                    new Book("剑来","烽火戏诸侯",35,320),
                    new Book("西游记","吴承恩",56,198),
                    new Book("三国演义","罗贯中",58,230),
                    new Book("水浒传","施耐庵",55,200),
                    new Book("红楼梦","曹雪芹",66,280)
            );
            return books;
        }
    复制代码

2.4.1 distinct()

先看源码上的解释:

返回不同元素组成的流 (即去重嘛~),规则就是:Object 中的 equals 方法。

所以需要注意的是:当我们实际要去用的时候,是需要重写 hashCode 与 equals 的,它会先比较 hashCode,hashCode 相同时则使用 equals 方法比较 (在 Lombok 就一个 @Data 啥都不用管了)

  1. 怎么用呢?代码如下:

        @Test
        public void test13(){
            List<Book> books = getBooks();
            books.stream()
                    .distinct()
                    .forEach(System.out::println);
        }
    复制代码

  2. 注意!!一定要重写 hashCode 和 equals ,不然就会失效了。如果使用 Lombok 的小伙伴可以试试把 Book 类中的 @Data 给注释了,加上个 @ToString 去看看没有重写的结果就知道了

    //@Data
    @ToString
    @AllArgsConstructor
    public class Book {
    
        private String bookName;
    
        private String author;
    
        private Integer age;
    
        private Integer price;
    }
    复制代码

    再跑一遍,就会看到这个集合原来怎么样,现在也还是怎么样 ( distinct() 失效了)。

2.4.2 sorted()

这个就是排序。在 Stream 中 sorted() 有两个重载方法,一个无参的,默认按自然排序 (即正序排序);另一个需要实现 Comparator 这个函数式接口,自己定义排序规则

Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
复制代码

那么我们就整个场景:按作者的年龄来排序

  1. 首先来瞅瞅无参的这个,先浅看一波源码

    可以看到 this.isNaturalSort = true 是否是自然排序设置了为 true,即下面那里调用个的这个方法: Comparator.naturalOrder()

    这个不扯那么远,大概的意思就是无参的这个排序 Stream 中默认使用了自然排序 (也就是正序了)

  2. 那既然他默认帮咱们做了排序了,那我们直接调来瞅瞅是啥样子的效果?

        @Test
        public void test14(){
            List<Book> books = getBooks();
            books.stream()
                    .sorted()
                    .forEach(System.out::println);
        }
    复制代码

    运行!映入眼前的是一片红...

不要慌,源码上有一句注释:Will throw CCE when we try to sort if T is not Comparable ,即如果T不可比较,当我们尝试排序时将抛出CCE (也就是当前的ClassCastException)。

确实咱把一个对象 Book 都扔过去了,谁知道你要比较啥?所以我们可以这样做:让 Book 这个类实现的 Comparable 接口 ,通过接口提供的 compareTo 方法来进行排序。

  1. 所以这个 Book 对象可以这样:

    @Data
    @AllArgsConstructor
    public class Book implements Comparable<Book>{
    
        private String bookName;
    
        private String author;
    
        private Integer age;
    
        private Integer price;
    
        @Override
        public int compareTo(@NotNull Book o) {
            return age - o.age;
        }
    }
    复制代码
  2. 再次运行,你会发现运行成功,且效果也与预期一样

    或许有些好兄弟已经发现了!咱们这样做,说到底还是通过实现了 Comparable接口 从而自定义了排序的规则,似乎和 sorted() 没啥关系。说白了,就是一顿 "脱裤子放屁" 的 XX 操作...

    确实,当前的场景下用这个无参的去排序本身就是不太合理的,它感觉更适合在某些较为单一的数据中去使用。所以在不一样的场景下,使用不一样的方法是很有必要的

  3. 在 Stream 中还给我们提供了另一个方法,那么此时我们就可以这样做了:

        @Test
        public void test14(){
            List<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值