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


完整的文章往这跳👉:
从基础到精通,一遍文章读懂 JDK8 Stream流 的使用!

关于Collectors工具类详解往这跳👉:
Collectors 工具类怎样用?看完这篇文章,或许你就懂了~

2.4 细说 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<Book> books = getBooks();
            books.stream()
                    .sorted(Comparator.comparingInt(Book::getAge))
                    .forEach(System.out::println);
        }
    

    即在 sorted(Comparator<? super T> comparator) 这个方法中里面是要一个 Comparator 的实现,而这个又是一个函数式接口,所以可以在里面使用 Lambda表达式,具体可以看我上一篇文章

    运行的结果也是一样的,就不粘出来了

2.4.3 filter()

条件过滤,根据具体的条件去过滤数据,而不满足的则会被剔除掉。

Stream<T> filter(Predicate<? super T> predicate);

直接看一个 Demo 吧:最近资金紧缺,过滤掉大于300元的书,买不起

    @Test
    public void test15(){
        List<Book> books = getBooks();
        books.stream()
                .filter(book -> book.getPrice() <= 300)
                .forEach(System.out::println);
    }

很简单的一个方法,想要实现怎样的效果,只需在方法中去定义自己的放回就可以了

2.4.4 forEach()

这个就不用多说啦~老熟客了,这个方法要传入一个 Consumer 函数接口对象,没有返回值

void forEach(Consumer<? super T> action);

当然,这个需要说明一下的是,该方法的在执行操作的时候,行为是不确定的,即在并行操作里面,该方法不能保证按顺序执行

感兴趣的朋友可以自己写个 Demo 用并行流去试一下,当数据量大的时候应该可以看出变化

2.4.5 forEachOrdered()

这个其实与 forEach() 是一样的,只是不同的是,该方法保证在串行流或者是并行流中都能够保证元素按顺序执行

void forEachOrdered(Consumer<? super T> action);
2.4.6 count()

这个也是在 Stream 流中非常简单的一个,它的作用:用于统计流中的元素数量,返回的 long 类型

long count();
2.4.7 max() & min()

这两个就跟孪生兄弟一样,相差不大。只是一个 获取流中最大的元素 ,一个则 获取流中最小的元素

Optional<T> max(Comparator<? super T> comparator);
Optional<T> min(Comparator<? super T> comparator);

这两个方法都需要传入一个 Comparator 函数式接口对象,该接口中有一个compare方法,用于自定义大小比较规则。

那么要怎样去用呢?这个与前面的 sorted 那里的也是一样的,大同小异。

  1. 找出哪本书价格最高

        @Test
        public void test16(){
            List<Book> books = getBooks();
            Book book = books.stream()
                    .max(Comparator.comparing(Book::getPrice))
                    .get();
            System.out.println("book = " + book);
        }
    
  2. 找出哪本书价格最低也是一样的,max 变成了 min 而已

        @Test
        public void test16(){
            List<Book> books = getBooks();
            Book book = books.stream()
                    .min(Comparator.comparing(Book::getPrice))
                    .get();
            System.out.println("book = " + book);
        }
    
  3. 或者说你有一串数字,要找出最大值或者最小值

        @Test
        public void test17() {
            Integer num = Stream.of(1, 2, 3, 4, 5, 6, 7, 18, 9, 10)
                    .max(Integer::compareTo)
                    .get();
            System.out.println("num = " + num);		// num = 18
        }
    

    或许你会有疑问,Integer::compareTo 这是啥?

    在 Integer 源码中可以看到 Integer 是实现了 Comparable<> 接口的,当然也重写了其 compareTo() 方法

        public int compareTo(Integer anotherInteger) {
            return compare(this.value, anotherInteger.value);
        }
    
        public static int compare(int x, int y) {
            return (x < y) ? -1 : ((x == y) ? 0 : 1);
        }
    
2.4.8 reduce()

reduce() 是一种聚合操作,即将多个值经过特定的计算后获取到的单个值。像上面已经介绍了的 count()max()min() 等都是聚合操作。

就像刚说的,你会发现其都是将流中多个值经过特定的计算后得到的单个值

reduce() 有三个重载方法

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);

Optional reduce(BinaryOperator accumulator);

这个与其他两个相比,应该是最为常用的一个了。和上面几个聚合函数一样,该函数的返回值也是 Optional 对象,因为结果存在空指针的情况。

  1. 求集合中元素的和

        @Test
        public void test18(){
            int i = Stream.of(1, 2, 3, 4, 5, 6, 7, 18, 9, 10)
                    .reduce((x, y) -> x + y)
                    .get();
            System.out.println("i = " + i);		// i = 65
        }
    

    即大概是这个意思,当然下面的相乘也是这个道理。最终的目的都还是将多个值经过特定的计算后获取到的单个值

在这里插入图片描述

  1. 求集合中元素的积

        @Test
        public void test18(){
            int i = Stream.of(1, 2, 3, 4, 5)
                    .reduce((x, y) -> x * y)
                    .get();
            System.out.println("i = " + i);		// i = 120
        }
    

    如果说想要更清晰的知道它是怎样执行的,也可以 DEBUG 去瞅瞅,或者像这个打印一下出来

        @Test
        public void test18(){
            int i = Stream.of(1, 2, 3, 4, 5, 6, 7, 18, 9, 10)
                    .reduce((x, y) -> {
                        System.out.println("x = " + x + "   " + "y =" + y);
                        return x + y;
                    }).get();
            System.out.println("i = " + i);		// i = 65
        }
    

T reduce(T identity, BinaryOperator accumulator);

T identity 类似于是一个默认值,即当集合为空时,就返回这个默认值;当然如果集合不为空时,这个值也会参与到计算当中

  1. 还是上面那个例子,就集合中元素的和

        @Test
        public void test19(){
            int i = Stream.of(1, 2, 3, 4, 5, 6, 7, 18, 9, 10)
                    .reduce(0, (x, y) -> x + y);
            System.out.println("i = " + i);     // i = 65
        }
    

    但是,但集合为空时,那么 T identity 这个就是充当默认值的角色了

        @Test
        public void test19(){
            List<Integer> list = new ArrayList<>();
            int i = list
                	.stream()
                    .reduce(0, (x, y) -> x + y);
            System.out.println("i = " + i);     // i = 0
        }
    

    那么集合不为空时,这个值也会参与到计算当中又当如何理解呢?试一下就知道了

        @Test
        public void test19(){
            int i = Stream.of(1, 2, 3, 4, 5, 6, 7, 18, 9, 10)
                    .reduce(5, (x, y) -> x + y);
            System.out.println("i = " + i);     // i = 70
    
            int j = Stream.of(1, 2, 3, 4, 5, 6, 7, 18, 9, 10)
                    .reduce(3, (x, y) -> x + y);
            System.out.println("j = " + j);     // j = 68
        }
    

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

这个就稍微复杂很多了。

在方法中我们可以看到有两个泛型:TU ,其中 T 是集合中的元素类型;而 U 是计算之后返回结果的类型,即 U 的类型是由第一个参数 identity 决定的

即该方法可以返回与集合中元素不同类型的值,而前两个方法则只能返回与集合中元素相同的值

像这样:

    @Test
    public void test21(){
        List<Book> books = Stream.of(
                new Book("剑来", "烽火", 38, 100),
                new Book("斗破", "土豆", 34, 60),
                new Book("完美", "辰东", 37, 70)
        ).collect(Collectors.toList());

        List<Integer> reduce = books.stream().reduce(new ArrayList<Integer>(), new BiFunction<ArrayList<Integer>, Book, ArrayList<Integer>>() {
            @Override
            public ArrayList<Integer> apply(ArrayList<Integer> integers, Book book) {
                integers.add(book.getPrice());
                System.out.println("list = " + integers);
                System.out.println("bookPrice = " + book.getPrice());
                return integers;
            }
        }, new BinaryOperator<ArrayList<Integer>>() {
            @Override
            public ArrayList<Integer> apply(ArrayList<Integer> integers1, ArrayList<Integer> integers2) {
                integers1.addAll(integers2);
                System.out.println("integers1 = " + integers1);
                System.out.println("integers2 = " + integers2);
                return integers1;
            }
        });

        System.out.println("finalList = " + reduce);
    }

运行之后的输出结果:

list = [100]
bookPrice = 100
list = [100, 60]
bookPrice = 60
list = [100, 60, 70]
bookPrice = 70
finalList = [100, 60, 70]

可以看到,经过一顿操作之后类型发生了转变,这个是没问题的;但有没有发现,似乎 BinaryOperator 中的方法没有打印出来?那让我们再看一个:

    @Test
    public void test20(){
        List<Book> books = Stream.of(
                new Book("剑来", "烽火", 38, 100),
                new Book("斗破", "土豆", 34, 60),
                new Book("完美", "辰东", 37, 70)
        ).collect(Collectors.toList());

        Integer i = books.parallelStream().reduce(0, new BiFunction<Integer, Book, Integer>() {
            @Override
            public Integer apply(Integer integer, Book book) {
                System.out.println("线程 " + Thread.currentThread().getId() + " ===> " + "integer = " + integer);
                System.out.println("线程 " + Thread.currentThread().getId() + " ===> " + "bookPrice = " + book.getPrice());
                return integer + book.getPrice();
            }
        }, new BinaryOperator<Integer>() {
            @Override
            public Integer apply(Integer integer1, Integer integer2) {
                System.out.println("线程 " + Thread.currentThread().getId() + " ===> " + "integer1 = " + integer1);
                System.out.println("线程 " + Thread.currentThread().getId() + " ===> " + "integer2 = " + integer2);
                return integer1 + integer2;
            }
        });

        System.out.println("i = " + i);
    }

stream() 换成了 parallelStream() ,即从串行流换成并行流,并且在打印前面加上当前线程的 ID ,运行后如下:

线程 1 ===> integer = 0
线程 17 ===> integer = 0
线程 16 ===> integer = 0
线程 16 ===> bookPrice = 100
线程 17 ===> bookPrice = 70
线程 1 ===> bookPrice = 60
线程 1 ===> integer1 = 60
线程 1 ===> integer2 = 70
线程 1 ===> integer1 = 100
线程 1 ===> integer2 = 130
i = 230

那么为什么 BinaryOperator 没有执行呢?这是因为 Stream 是支持并发操作的,为了避免竞争,对于 reduce 这个方法,线程都会有独立的 result,BinaryOperator combiner 的作用在于汇总所有线程的计算结果,从而得到一个最终的 result

上述可以多运行几次或者多加一些数据量去观察规律,进程在多线程中都会争夺时间片,因此每次运行的结果不一定相同

2.4.9 limit() & skip()
  • limit :限制,截取流中指定数量的元素
  • skip :跳过,跳过流中指定数量的元素
  1. 获取最便宜的3本书

        @Test
        public void test22(){
            List<Book> books = getBooks();
            books.stream()
                    .sorted(Comparator.comparing(Book::getPrice))   // 排序
                    .limit(3)                                       // 截取
                    .forEach(System.out::println);                  // 打印输出
        }
    
  2. 跳过也是一样的,跳过最贵的5本书

        @Test
        public void test22(){
            List<Book> books = getBooks();
            books.stream()
                    .sorted(Comparator.comparing(Book::getPrice,Comparator.reverseOrder()))     // 排序
                    .skip(5)                                                                    // 截取
                    .forEach(System.out::println);                                              // 打印输出
        }
    

这两个比较简单,直接对流中的元素使用即可

2.4.10 allMatch() & anyMatch() & noneMatch()

这三个算是一组的,返回的都是布尔类型,用于对一些逻辑的判断。

boolean allMatch(Predicate<? super T> predicate);

boolean anyMatch(Predicate<? super T> predicate);

boolean noneMatch(Predicate<? super T> predicate);
  • allMatch() 当流中的元素都按指定的规则匹配上,才会返回 true (即全部对才对)
  • anyMatch() 当流中有任意元素满足指定的规则时,返回 true (即对一个就对了)
  • noneMatch() 当流中所有元素都没有与指定的规则匹配上,才会返回 true (即全部错了才是对的)
  1. 是否所有的书都大于60元

        @Test
        public void test23(){
            List<Book> books = Stream.of(
                    new Book("剑来", "烽火", 38, 100),
                    new Book("斗破", "土豆", 34, 60),
                    new Book("完美", "辰东", 37, 70),
                    new Book("斗罗", "三少", 36, 80)
            ).collect(Collectors.toList());
    
            boolean b = books.stream().allMatch(book -> book.getPrice() > 60);
            System.out.println("是否所有的书都大于60元 = " + b);      // false
        }
    

    allMatch() 所有都满足,返回 true,否之则 false

  2. 是否有高于60元的书

        @Test
        public void test23(){
            List<Book> books = Stream.of(
                    new Book("剑来", "烽火", 38, 100),
                    new Book("斗破", "土豆", 34, 60),
                    new Book("完美", "辰东", 37, 70),
                    new Book("斗罗", "三少", 36, 80)
            ).collect(Collectors.toList());
    
            boolean b = books.stream().anyMatch(book -> book.getPrice() > 60);
            System.out.println("是否有高于60元的书 = " + b);      // true
        }
    

    anyMatch() 有一个满足,返回 true,否之则 false

  3. 第三个的例子其实有点难举,因为个人感觉有点变扭。

        @Test
        public void test23(){
            List<Book> books = Stream.of(
                    new Book("剑来", "烽火", 38, 100),
                    new Book("斗破", "土豆", 34, 60),
                    new Book("完美", "辰东", 37, 70),
                    new Book("斗罗", "三少", 36, 80)
            ).collect(Collectors.toList());
    
            boolean b = books.stream().noneMatch(book -> book.getPrice() > 110);
            System.out.println("b = " + b);      // true
        }
    

    这个有点像是与 allMatch() 反着来,只有当流中的所有元素,都不满足指定的规则时,才会返回 true,否之则 false

    这个多调整几次数据,运行几遍看看效果便能琢磨出规律。

2.4.11 map()
<R> Stream<R> map(Function<? super T, ? extends R> mapper);

这个方法提供了一个映射规则,对流中的数据进行映射,从而用新的数据替换旧的数据

这个方法的使用频率很高,而且也非常的实用

  1. 获取书的名称

        @Test
        public void test25(){
            List<Book> books = Stream.of(
                    new Book("剑来", "烽火", 38, 100),
                    new Book("斗破", "土豆", 34, 60),
                    new Book("完美", "辰东", 37, 70),
                    new Book("斗罗", "三少", 36, 80)
            ).collect(Collectors.toList());
    
            books.stream()
                    .map(Book::getBookName)
                    .forEach(System.out::println);
        }
    
  2. 当然你也可以这样,不过这里需要把你想要的数据 return 出去

        @Test
        public void test25(){
            List<Book> books = Stream.of(
                    new Book("剑来", "烽火", 38, 100),
                    new Book("斗破", "土豆", 34, 60),
                    new Book("完美", "辰东", 37, 70),
                    new Book("斗罗", "三少", 36, 80)
            ).collect(Collectors.toList());
    
            books.stream()
                    .map(book -> {
                        String bookName = book.getBookName();
                        String author = book.getAuthor();
                        return bookName + "---" + author;
                    })
                    .forEach(System.out::println);
        }
    
2.4.12 flatMap()

扁平化映射,其实本质上与 map() 是一样的,都是对流中的元素进行一定的处理然后再返回出来

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

那么什么时候使用 flatMap() 什么时候又使用 map() 呢?

网上大佬一句话总结:多层数据结构转单层时用 flatmap(),单层转单层或者多层转多层用 map()

  1. 那么我们试一下在集合里面放数组是个怎样的效果

        @Test
        public void test26() {
            List<String[]> collect = Stream.of(
                    new String[]{"a,b,c"},
                    new String[]{"d,e,f"},
                    new String[]{"g,h,j"}
            ).collect(Collectors.toList());
    
            collect.stream()
                    .flatMap(new Function<String[], Stream<?>>() {
                        @Override
                        public Stream<?> apply(String[] strings) {
                            // 可以看到,流中的元素是数组。那么我们可以将数组装换成 Stream 类型来处理
                            return Arrays.stream(strings);
                        }
                    })
                    .forEach(System.out::println);
        }
    

    我们以往处理的时候,在集合中只有一种数据结构;而此时集合里面放的是数组,那么此时这个 扁平化 这个操作就用的上了

    先对集合中的数据结构作处理,然后再进行数据处理

  2. 也还可以这样玩一下:把里面的字母变成大写

        @Test
        public void test27() {
            List<String[]> collect = Stream.of(
                    new String[]{"a,b,c"},
                    new String[]{"d,e,f"},
                    new String[]{"g,h,j"}
            ).collect(Collectors.toList());
    
            collect.stream()
                    .flatMap(Arrays::stream)
                    .map(String::toUpperCase)
                    .forEach(System.out::println);
        }
    

    这里用的是 Lambda 表达式的形式

2.4.13 mapToInt() & mapToDouble() & mapToLong()
IntStream mapToInt(ToIntFunction<? super T> mapper);

DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);

LongStream mapToLong(ToLongFunction<? super T> mapper);

这几个方法比较好玩,将流中的元素转换成了 IntStream/DoubleStream/LongStream 从而可以进行一些运算,比如:获取数据最大值、最小值、数据量、平均值等

  1. 获取数据最大值

        @Test
        public void test28() {
            int i = Stream.of(1, 2, 3, 4, 5, 6, 7, 18, 9, 10)
                    .mapToInt(value -> value)
                    .max()
                    .getAsInt();
            System.out.println("i = " + i);		// 18
        }
    
  2. 获取数据的和

        @Test
        public void test28() {
            int i = Stream.of(1, 2, 3, 4, 5, 6, 7, 18, 9, 10)
                    .mapToInt(value -> value)
                    .sum();
            System.out.println("i = " + i);		// 65
        }
    
  3. 获取数据的平均值

        @Test
        public void test28() {
            double i = Stream.of(1, 2, 3, 4, 5, 6, 7, 18, 9, 10)
                    .mapToInt(value -> value)
                    .average()
                    .getAsDouble();
            System.out.println("i = " + i);		// 6.5
        }
    
  4. 也可以对这组数据进行分析

        @Test
        public void test28() {
            IntSummaryStatistics statistics = Stream.of(1, 2, 3, 4, 5, 6, 7, 18, 9, 10)
                    .mapToInt(value -> value)
                    .summaryStatistics();
            System.out.println("数据分析 = " + statistics);		// 数据分析 : IntSummaryStatistics{count=10, sum=65, min=1, average=6.500000, max=18}
        }
    

这个一组与之对应的还有一些 扁平化 的操作:

IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);

DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);

LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);

本质上是与上面是一样的,什么时候用哪个,围绕这句话即可: 多层数据结构转单层时用 flat 的,单层转单层或者多层转多层用普通的

2.4.14 collect()

这个可能是用的最多的几个方法之一了吧

    <R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner);
                  
	<R, A> R collect(Collector<? super T, A, R> collector);

collect() 多参的方法,我似乎没见人用过。不过在源码上写了一两个例子可以瞅瞅

        // 将字符串累积到ArrayList中   stringStream 假设该流是存在的
        List<String> asList = stringStream.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

        // 将获取一个字符串流并将它们连接成一个字符串   stringStream 假设该流是存在的
        String concat = stringStream.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString();

用的最多的还是这个 collect() 单参的方法 ,那么就不得不说一下 Collectors

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天怎么不会塌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值