Java8新特性之Stream流(含具体案例)

一、概述

Stream流是 Java 8 新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选、排序、聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由终端操作 (terminal operation) 得到前面处理的结果。Stream 流可以极大的提高开发效率,也可以使用它写出更加简洁明了的代码。我自从接触过 Stream 流之后,可以说对它爱不释手。

二、Stream的创建

Stream可以通过集合数组创建。

1、通过java.util.Collection.stream()方法用集合创建流

List<string> list = Arrays.asList("a", "b", "c");
// &#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x987A;&#x5E8F;&#x6D41;
Stream<string> stream = list.stream();
// &#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x5E76;&#x884C;&#x6D41;
Stream<string> parallelStream = list.parallelStream();</string></string></string>

2、使用 java.util.Arrays.stream(T[] array)方法用数组创建流

int[] array={1,3,5,7,9};
IntStream stream = Arrays.stream(array);

3、使用 Stream的静态方法: of()&#x3001;iterate()&#x3001;generate()

Stream<integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

Stream<integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
stream2.forEach(System.out::println);

Stream<double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);</double></integer></integer>

输出结果:

0 3 6 9
0.6796156909271994
0.1914314208854283
0.8116932592396652

streamparallelStream的简单区分:

stream是顺序流,由主线程按顺序对流执行操作,而parallelStream是并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。如果流中的数据量足够大,并行流可以加快处速度。除了直接创建并行流,还可以通过parallel()把顺序流转换成并行流:

Optional<integer> findFirst = list.stream().parallel().filter(x->x>6).findFirst();</integer>

三、Stream的使用(具体案例)

案例中用到的员工类:

/**
 * @description: &#x5458;&#x5DE5;
 * @author: admin
 */
@Data
public class Person {

    /*** &#x59D3;&#x540D;*/
    private String name;
    /*** &#x85AA;&#x8D44;*/
    private Integer salary;
    /*** &#x5E74;&#x9F84;*/
    private Integer age;
    /*** &#x6027;&#x522B;*/
    private String sex;
    /*** &#x5730;&#x533A;*/
    private String area;

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

}

1.遍历/匹配(foreach/find/match)

Stream也是支持类似集合的遍历和匹配元素的,只是 Stream中的元素是以 Optional类型存在的。 Stream的遍历、匹配非常的简单。

    public static void main(String[] args) {

        List<integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);

        // &#x904D;&#x5386;&#x8F93;&#x51FA;&#x7B26;&#x5408;&#x6761;&#x4EF6;&#x7684;&#x5143;&#x7D20;
        List<integer> collect = list.stream().filter(x -> x > 6).collect(Collectors.toList());
        // &#x5339;&#x914D;&#x7B2C;&#x4E00;&#x4E2A;
        Optional<integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
        // &#x5339;&#x914D;&#x4EFB;&#x610F;&#xFF08;&#x9002;&#x7528;&#x4E8E;&#x5E76;&#x884C;&#x6D41;&#xFF09;
        Optional<integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
        // &#x662F;&#x5426;&#x5305;&#x542B;&#x7B26;&#x5408;&#x7279;&#x5B9A;&#x6761;&#x4EF6;&#x7684;&#x5143;&#x7D20;
        boolean anyMatch = list.stream().anyMatch(x -> x > 6);
        System.out.println("&#x5927;&#x4E8E;6&#x7684;&#x503C;&#xFF1A;" + collect);
        System.out.println("&#x5339;&#x914D;&#x7B2C;&#x4E00;&#x4E2A;&#x503C;&#xFF1A;" + findFirst.get());
        System.out.println("&#x5339;&#x914D;&#x4EFB;&#x610F;&#x4E00;&#x4E2A;&#x503C;&#xFF1A;" + findAny.get());
        System.out.println("&#x662F;&#x5426;&#x5B58;&#x5728;&#x5927;&#x4E8E;6&#x7684;&#x503C;&#xFF1A;" + anyMatch);
    }</integer></integer></integer></integer>

结果:

Java8新特性之Stream流(含具体案例)

2.筛选(filter)

筛选,是按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中的操作。

    public static void main(String[] args) {

        List<person> personList = new ArrayList<>();
        personList.add(new Person("&#x5F20;&#x4E09;", 1000, 20, "&#x7537;", "&#x5317;&#x4EAC;"));
        personList.add(new Person("&#x674E;&#x56DB;", 2000, 21, "&#x7537;", "&#x5357;&#x4EAC;"));
        personList.add(new Person("&#x738B;&#x4E94;", 3000, 20, "&#x5973;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x8D75;&#x516D;", 4000, 22, "&#x7537;", "&#x56DB;&#x5DDD;"));
        personList.add(new Person("&#x5B59;&#x4E03;", 5000, 25, "&#x5973;", "&#x4E0A;&#x6D77;"));

        // &#x7B5B;&#x9009;&#x51FA;&#x5DE5;&#x4F5C;&#x9AD8;&#x4E8E;3000&#x7684;&#x5458;&#x5DE5;
        List<string> list = personList.stream().filter(p -> p.getSalary() > 3000).map(Person::getName).collect(Collectors.toList());
        System.out.println("&#x85AA;&#x8D44;&#x9AD8;&#x4E8E;3000&#x5143;&#x7684;&#x5458;&#x5DE5;&#xFF1A;" + list);
    }</string></person>

结果:

Java8新特性之Stream流(含具体案例)

3.聚合(max/min/count)

maxmincount 这些大家都不陌生,在mysql中我们常用它们进行数据运算和统计。Java stream中也引入了这些概念和用法,极大地方便了我们对集合、数组的数据统计工作。

    public static void main(String[] args) {

        List<person> personList = new ArrayList<>();
        personList.add(new Person("&#x5F20;&#x4E09;", 1000, 20, "&#x7537;", "&#x5317;&#x4EAC;"));
        personList.add(new Person("&#x674E;&#x56DB;", 2000, 21, "&#x7537;", "&#x5357;&#x4EAC;"));
        personList.add(new Person("&#x738B;&#x4E94;", 3000, 20, "&#x5973;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x8D75;&#x516D;", 4000, 22, "&#x7537;", "&#x56DB;&#x5DDD;"));
        personList.add(new Person("&#x5B59;&#x4E03;", 5000, 25, "&#x5973;", "&#x4E0A;&#x6D77;"));

        // &#x83B7;&#x53D6;&#x5DE5;&#x8D44;&#x6700;&#x9AD8;&#x7684;&#x5458;&#x5DE5;
        Optional<person> max = personList.stream().max(Comparator.comparingInt(Person::getSalary));
        System.out.println("&#x5458;&#x5DE5;&#x5DE5;&#x8D44;&#x6700;&#x5927;&#x503C;&#xFF1A;" + max.get().getSalary());

        // &#x8BA1;&#x7B97;&#x5DE5;&#x8D44;&#x5927;&#x4E8E;2000&#x7684;&#x6709;&#x591A;&#x5C11;&#x4EBA;
        long count = personList.stream().filter(p -> p.getSalary() > 2000).count();
        System.out.println("&#x5DE5;&#x8D44;&#x5927;&#x4E8E;2000&#x5143;&#x7684;&#x4EBA;&#x6570;&#xFF1A;" + count);

        // &#x8BA1;&#x7B97;&#x6240;&#x6709;&#x5458;&#x5DE5;&#x5DE5;&#x8D44;&#x603B;&#x548C;
        int sum = personList.stream().mapToInt(Person::getSalary).sum();
        System.out.println("&#x6240;&#x6709;&#x5458;&#x5DE5;&#x5DE5;&#x8D44;&#x603B;&#x548C;&#xFF1A;" + sum);
    }</person></person>

结果:

Java8新特性之Stream流(含具体案例)

4.映射(map/flatMap)

映射,可以将一个流的元素按照一定的映射规则映射到另一个流中。分为 mapflatMap

  • map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  • flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
   public static void main(String[] args) {

        List<person> personList = new ArrayList<>();
        personList.add(new Person("&#x5F20;&#x4E09;", 1000, 20, "&#x7537;", "&#x5317;&#x4EAC;"));
        personList.add(new Person("&#x674E;&#x56DB;", 2000, 21, "&#x7537;", "&#x5357;&#x4EAC;"));
        personList.add(new Person("&#x738B;&#x4E94;", 3000, 20, "&#x5973;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x8D75;&#x516D;", 4000, 22, "&#x7537;", "&#x56DB;&#x5DDD;"));
        personList.add(new Person("&#x5B59;&#x4E03;", 5000, 25, "&#x5973;", "&#x4E0A;&#x6D77;"));

        // &#x5C06;&#x5458;&#x5DE5;&#x5DE5;&#x4F5C;&#x5168;&#x90E8;&#x589E;&#x52A0;10000&#x5143;
        // 1&#x3001;&#x65B9;&#x5F0F;&#x4E00;&#xFF1A;&#x4E0D;&#x6539;&#x53D8;&#x539F;&#x6765;&#x5458;&#x5DE5;&#x96C6;&#x5408;
        List<person> personListNew = personList.stream().map(person -> {
            Person personNew = new Person(person.getName(), 0, 0, null, null);
            personNew.setSalary(person.getSalary() + 10000);
            return personNew;
        }).collect(Collectors.toList());
        System.out.println("&#x4E00;&#x6B21;&#x6539;&#x52A8;&#x524D;&#xFF1A;" + personList.get(0).getName() + ">>>" + personList.get(0).getSalary());
        System.out.println("&#x4E00;&#x6B21;&#x6539;&#x52A8;&#x540E;&#xFF1A;" + personListNew.get(0).getName() + ">>>" + personListNew.get(0).getSalary());

        // 2&#x3001;&#x65B9;&#x5F0F;&#x4E8C;&#xFF1A;&#x6539;&#x53D8;&#x539F;&#x6765;&#x5458;&#x5DE5;&#x96C6;&#x5408;&#x7684;&#x65B9;&#x5F0F;
        List<person> personListNew2 = personList.stream().map(person -> {
            person.setSalary(person.getSalary() + 10000);
            return person;
        }).collect(Collectors.toList());
        System.out.println("&#x4E8C;&#x6B21;&#x6539;&#x52A8;&#x524D;&#xFF1A;" + personList.get(0).getName() + ">>>" + personListNew.get(0).getSalary());
        System.out.println("&#x4E8C;&#x6B21;&#x6539;&#x52A8;&#x540E;&#xFF1A;" + personListNew2.get(0).getName() + ">>>" + personListNew.get(0).getSalary());

        // &#x5C06;&#x4E24;&#x4E2A;&#x5B57;&#x7B26;&#x6570;&#x7EC4;&#x5408;&#x5E76;&#x6210;&#x4E00;&#x4E2A;&#x65B0;&#x7684;&#x5B57;&#x7B26;&#x6570;&#x7EC4;
        List<string> list = Arrays.asList("Hello", "World");
        Stream<string> map = list.stream().map(s -> s.split("")).flatMap(Arrays::stream);
        map.forEach(System.out::print);
        System.out.println();

        // &#x7ED9;&#x5B9A;&#x4E24;&#x4E2A;&#x6570;&#x5B57;&#x5217;&#x8868; &#x83B7;&#x53D6;&#x6240;&#x6709;&#x7684;&#x6570;&#x5BF9;
        List<integer> numbers1 = Arrays.asList(1, 2, 3);
        List<integer> numbers2 = Arrays.asList(3, 4);
        // flatMap&#x5347;&#x7EF4;&#x5EA6;
        List<int[]> pairs = numbers1.stream().flatMap(x -> numbers2.stream().map(y -> new int[] { x, y }))
                .collect(Collectors.toList());
        for (int[] pair : pairs) {
            System.out.print(Arrays.toString(pair));
        }

    }</int[]></integer></integer></string></string></person></person></person>

结果:

Java8新特性之Stream流(含具体案例)

5.归约(reduce)

归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。

public static void main(String[] args) {

        List<person> personList = new ArrayList<>();
        personList.add(new Person("&#x5F20;&#x4E09;", 1000, 20, "&#x7537;", "&#x5317;&#x4EAC;"));
        personList.add(new Person("&#x674E;&#x56DB;", 2000, 21, "&#x7537;", "&#x5357;&#x4EAC;"));
        personList.add(new Person("&#x738B;&#x4E94;", 3000, 20, "&#x5973;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x8D75;&#x516D;", 4000, 22, "&#x7537;", "&#x56DB;&#x5DDD;"));
        personList.add(new Person("&#x5B59;&#x4E03;", 5000, 25, "&#x5973;", "&#x4E0A;&#x6D77;"));

        // &#x6C42;&#x6240;&#x6709;&#x5458;&#x5DE5;&#x7684;&#x5DE5;&#x8D44;&#x4E4B;&#x548C;&#x3001;&#x6700;&#x9AD8;&#x5DE5;&#x8D44;
        // &#x6C42;&#x5DE5;&#x8D44;&#x4E4B;&#x548C;&#x65B9;&#x6CD5;1&#xFF1A;
        Optional<integer> sumSalary = personList.stream().map(Person::getSalary).reduce(Integer::sum);
        // &#x6C42;&#x5DE5;&#x8D44;&#x4E4B;&#x548C;&#x65B9;&#x6CD5;2&#xFF1A;
        Integer sumSalary2 = personList.stream().reduce(0, (sum, p) -> sum += p.getSalary(), Integer::sum);

        // &#x6C42;&#x6700;&#x9AD8;&#x5DE5;&#x8D44;&#x65B9;&#x6CD5;1&#xFF1A;
        Integer maxSalary = personList.stream().reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(), Integer::max);
        // &#x6C42;&#x6700;&#x9AD8;&#x5DE5;&#x8D44;&#x65B9;&#x6CD5;2&#xFF1A;
        Integer maxSalary2 = personList.stream().reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(), (max1, max2) -> max1 > max2 ? max1 : max2);
        // &#x6C42;&#x6700;&#x9AD8;&#x5DE5;&#x8D44;&#x65B9;&#x6CD5;3&#xFF1A;
        Integer maxSalary3 = personList.stream().map(Person::getSalary).reduce(Integer::max).get();
        System.out.println("&#x5DE5;&#x8D44;&#x4E4B;&#x548C;&#xFF0C;&#x65B9;&#x6CD5;1&#xFF1A;" + sumSalary);
        System.out.println("&#x5DE5;&#x8D44;&#x4E4B;&#x548C;&#xFF0C;&#x65B9;&#x6CD5;2&#xFF1A;" + sumSalary2);
        System.out.println("&#x6700;&#x9AD8;&#x5DE5;&#x8D44;&#xFF0C;&#x65B9;&#x6CD5;1&#xFF1A;" + maxSalary);
        System.out.println("&#x6700;&#x9AD8;&#x5DE5;&#x8D44;&#xFF0C;&#x65B9;&#x6CD5;2&#xFF1A;" + maxSalary2);
        System.out.println("&#x6700;&#x9AD8;&#x5DE5;&#x8D44;&#xFF0C;&#x65B9;&#x6CD5;3&#xFF1A;" + maxSalary3);
    }</integer></person>

结果:

Java8新特性之Stream流(含具体案例)

6.收集(collect)

collect,收集,可以说是内容最繁多、功能最丰富的部分了。从字面上去理解,就是把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合。

collect主要依赖 java.util.stream.Collectors类内置的静态方法。

6.1归集(toList/toSet/toMap)

因为流不存储数据,那么在流中的数据完成处理后,需要将流中的数据重新归集到新的集合里。toList、toSet和toMap比较常用,另外还有toCollection、toConcurrentMap等复杂一些的用法。

下面用一个案例演示toList、toSet和toMap:

public static void main(String[] args) {

        List<integer> list = Arrays.asList(1, 3, 4, 8, 6, 2, 20, 13);
        List<integer> list1 = list.stream().filter(a -> a % 2 == 0).collect(Collectors.toList());
        Set<integer> list2 = list.stream().filter(a -> a % 2 == 0).collect(Collectors.toSet());
        System.out.println("&#x88AB;2&#x6574;&#x9664;&#x7684;list&#x96C6;&#x5408;" + list1);
        System.out.println("&#x88AB;2&#x6574;&#x9664;&#x7684;set&#x96C6;&#x5408;" + list2);

        List<person> personList = new ArrayList<>();
        personList.add(new Person("&#x5F20;&#x4E09;", 1000, 20, "&#x7537;", "&#x5317;&#x4EAC;"));
        personList.add(new Person("&#x674E;&#x56DB;", 2000, 21, "&#x7537;", "&#x5357;&#x4EAC;"));
        personList.add(new Person("&#x738B;&#x4E94;", 3000, 20, "&#x5973;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x8D75;&#x516D;", 4000, 22, "&#x7537;", "&#x56DB;&#x5DDD;"));
        personList.add(new Person("&#x5B59;&#x4E03;", 5000, 25, "&#x5973;", "&#x4E0A;&#x6D77;"));
        // &#x5DE5;&#x8D44;&#x5927;&#x4E8E;3000&#x5143;&#x7684;&#x5458;&#x5DE5;
        Map<string, integer> map = personList.stream().filter(person -> person.getSalary() > 3000).collect(Collectors.toMap(Person::getName, person -> person.getSalary()));
        System.out.println("&#x5DE5;&#x8D44;&#x5927;&#x4E8E;3000&#x5143;&#x7684;&#x5458;&#x5DE5;:" + map);
    }</string,></person></integer></integer></integer>

结果:

Java8新特性之Stream流(含具体案例)

6.2统计(count/averaging)

Collectors提供了一系列用于数据统计的静态方法:

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

    public static void main(String[] args) {

        List<person> personList = new ArrayList<>();
        personList.add(new Person("&#x5F20;&#x4E09;", 1000, 20, "&#x7537;", "&#x5317;&#x4EAC;"));
        personList.add(new Person("&#x674E;&#x56DB;", 2000, 21, "&#x7537;", "&#x5357;&#x4EAC;"));
        personList.add(new Person("&#x738B;&#x4E94;", 3000, 20, "&#x5973;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x8D75;&#x516D;", 4000, 22, "&#x7537;", "&#x56DB;&#x5DDD;"));
        personList.add(new Person("&#x5B59;&#x4E03;", 5000, 25, "&#x5973;", "&#x4E0A;&#x6D77;"));

        // &#x7EDF;&#x8BA1;&#x5458;&#x5DE5;&#x4EBA;&#x6570;&#x3001;&#x5E73;&#x5747;&#x5DE5;&#x8D44;&#x3001;&#x5DE5;&#x8D44;&#x603B;&#x989D;&#x3001;&#x6700;&#x9AD8;&#x5DE5;&#x8D44;
        // &#x5458;&#x5DE5;&#x603B;&#x4EBA;&#x6570;
        long count = personList.stream().count();
        // &#x5E73;&#x5747;&#x5DE5;&#x8D44;
        Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
        // &#x6700;&#x9AD8;&#x5DE5;&#x8D44;
        Optional<integer> max = personList.stream().map(Person::getSalary).max(Integer::compare);
        // &#x5DE5;&#x8D44;&#x4E4B;&#x548C;
        int sum = personList.stream().mapToInt(Person::getSalary).sum();
        // &#x4E00;&#x6B21;&#x6027;&#x7EDF;&#x8BA1;&#x6240;&#x6709;&#x4FE1;&#x606F;
        DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));

        System.out.println("&#x5458;&#x5DE5;&#x603B;&#x4EBA;&#x6570;&#xFF1A;" + count);
        System.out.println("&#x5458;&#x5DE5;&#x5E73;&#x5747;&#x5DE5;&#x8D44;&#xFF1A;" + average);
        System.out.println("&#x5458;&#x5DE5;&#x5DE5;&#x8D44;&#x603B;&#x548C;&#xFF1A;" + sum);
        System.out.println("&#x5458;&#x5DE5;&#x5DE5;&#x8D44;&#x6240;&#x6709;&#x7EDF;&#x8BA1;&#xFF1A;" + collect);
    }</integer></person>

结果:

Java8新特性之Stream流(含具体案例)

6.3 分组(partitioningBy/groupingBy)

  • 分区:将 stream按条件分为两个 Map,比如员工按薪资是否高于8000分为两部分。
  • 分组:将集合分为多个Map,比如员工按性别分组。有单级分组和多级分组。
    public static void main(String[] args) {

        List<person> personList = new ArrayList<>();
        personList.add(new Person("&#x5F20;&#x4E09;", 1000, 20, "&#x7537;", "&#x5317;&#x4EAC;"));
        personList.add(new Person("&#x674E;&#x56DB;", 2000, 21, "&#x7537;", "&#x5357;&#x4EAC;"));
        personList.add(new Person("&#x738B;&#x4E94;", 3000, 20, "&#x5973;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x8D75;&#x516D;", 4000, 22, "&#x7537;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x5B59;&#x4E03;", 5000, 25, "&#x5973;", "&#x4E0A;&#x6D77;"));

        // &#x6309;&#x85AA;&#x8D44;&#x9AD8;&#x4E8E;3000&#x5206;&#x7EC4;
        Map<boolean, list<person>> salaryGroup = personList.stream().collect(Collectors.partitioningBy(p -> p.getSalary() > 3000));
        List<person> group1 = salaryGroup.get(true);
        List<person> group2 = salaryGroup.get(false);
        for (Person person : group1) {
            System.out.println("&#x85AA;&#x8D44;&#x9AD8;&#x4E8E;3000&#x5143;&#x7EC4;&#xFF1A;" + person);
        }
        for (Person person : group2) {
            System.out.println("&#x85AA;&#x8D44;&#x4F4E;&#x4E8E;3000&#x5143;&#x7EC4;&#xFF1A;" + person);
        }

        // &#x6309;&#x6027;&#x522B;&#x5206;&#x7EC4;
        Map<string, list<person>> sexGroup = personList.stream().collect(Collectors.groupingBy(Person::getSex));
        List<person> group3 = sexGroup.get("&#x7537;");
        List<person> group4 = sexGroup.get("&#x5973;");
        for (Person person : group3) {
            System.out.println("&#x7537;&#x5B50;&#x7EC4;&#xFF1A;" + person);
        }
        for (Person person : group4) {
            System.out.println("&#x5973;&#x5B50;&#x7EC4;&#xFF1A;" + person);
        }

        // &#x5C06;&#x5458;&#x5DE5;&#x5148;&#x6309;&#x6027;&#x522B;&#x5206;&#x7EC4;&#xFF0C;&#x518D;&#x6309;&#x5730;&#x533A;&#x5206;&#x7EC4;
        Map<string, map<string, list<person>>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
        Map<string, list<person>> manGroup = group.get("&#x7537;");
        Map<string, list<person>> womenGroup = group.get("&#x5973;");
        List<person> group5 = manGroup.get("&#x5408;&#x80A5;");
        List<person> group6 = womenGroup.get("&#x4E0A;&#x6D77;");
        System.out.println("&#x5730;&#x533A;&#x5728;&#x5408;&#x80A5;&#x7684;&#x7537;&#x5B50;&#x7EC4;&#xFF1A;" + group5);
        System.out.println("&#x5730;&#x533A;&#x5728;&#x4E0A;&#x6D77;&#x7684;&#x5973;&#x5B50;&#x7EC4;&#xFF1A;" + group6);
    }</person></person></string,></string,></string,></person></person></string,></person></person></boolean,></person>

结果:

Java8新特性之Stream流(含具体案例)

6.4接合(joining)

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

    public static void main(String[] args) {

        List<person> personList = new ArrayList<>();
        personList.add(new Person("&#x5F20;&#x4E09;", 1000, 20, "&#x7537;", "&#x5317;&#x4EAC;"));
        personList.add(new Person("&#x674E;&#x56DB;", 2000, 21, "&#x7537;", "&#x5357;&#x4EAC;"));
        personList.add(new Person("&#x738B;&#x4E94;", 3000, 20, "&#x5973;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x8D75;&#x516D;", 4000, 22, "&#x7537;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x5B59;&#x4E03;", 5000, 25, "&#x5973;", "&#x4E0A;&#x6D77;"));

        String persons = personList.stream().map(p -> p.getName() + "-" + p.getSex() + "-" + p.getSalary()).collect(Collectors.joining(","));
        System.out.println("&#x6240;&#x6709;&#x5458;&#x5DE5;&#x4FE1;&#x606F;&#xFF1A;" + persons);
    }</person>

结果:

Java8新特性之Stream流(含具体案例)

6.5归约(reducing)

Collectors类提供的 reducing方法,相比于 stream本身的 reduce方法,增加了对自定义归约的支持。

    public static void main(String[] args) {

        List<person> personList = new ArrayList<>();
        personList.add(new Person("&#x5F20;&#x4E09;", 6000, 20, "&#x7537;", "&#x5317;&#x4EAC;"));
        personList.add(new Person("&#x674E;&#x56DB;", 6500, 21, "&#x7537;", "&#x5357;&#x4EAC;"));
        personList.add(new Person("&#x738B;&#x4E94;", 7300, 20, "&#x5973;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x8D75;&#x516D;", 8000, 22, "&#x7537;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x5B59;&#x4E03;", 9860, 25, "&#x5973;", "&#x4E0A;&#x6D77;"));

        // &#x6BCF;&#x4E2A;&#x5458;&#x5DE5;&#x51CF;&#x53BB;&#x8D77;&#x5F81;&#x70B9;&#x540E;&#x7684;&#x85AA;&#x8D44;&#x4E4B;&#x548C;&#xFF08;&#x8FD9;&#x91CC;&#x4E2A;&#x7A0E;&#x7684;&#x7B97;&#x6CD5;&#x5E76;&#x4E0D;&#x6B63;&#x786E;&#xFF0C;&#x4F46;&#x6CA1;&#x60F3;&#x5230;&#x66F4;&#x597D;&#x7684;&#x4F8B;&#x5B50;&#xFF09;
        Integer sum = personList.stream().map(Person::getSalary).reduce(0, (i, j) -> (i + j - 5000));
        System.out.println("&#x5458;&#x5DE5;&#x6263;&#x7A0E;&#x85AA;&#x8D44;&#x603B;&#x548C;&#xFF1A;" + sum);

        // stream&#x7684;reduce
        Optional<integer> sum2 = personList.stream().map(Person::getSalary).reduce(Integer::sum);
        System.out.println("&#x5458;&#x5DE5;&#x85AA;&#x8D44;&#x603B;&#x548C;&#xFF1A;" + sum2.get());
    }</integer></person>

结果:

Java8新特性之Stream流(含具体案例)

7.排序(sorted)

sorted,中间操作。有两种排序:

  • sorted():自然排序,流中元素需实现Comparable接口
  • sorted(Comparator com):Comparator排序器自定义排序
    public static void main(String[] args) {

        List<person> personList = new ArrayList<>();
        personList.add(new Person("&#x5F20;&#x4E09;", 16000, 20, "&#x7537;", "&#x5317;&#x4EAC;"));
        personList.add(new Person("&#x674E;&#x56DB;", 8500, 21, "&#x7537;", "&#x5357;&#x4EAC;"));
        personList.add(new Person("&#x738B;&#x4E94;", 7300, 20, "&#x5973;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x8D75;&#x516D;", 8000, 22, "&#x7537;", "&#x5408;&#x80A5;"));
        personList.add(new Person("&#x5B59;&#x4E03;", 15860, 25, "&#x5973;", "&#x4E0A;&#x6D77;"));

        // &#x6309;&#x5DE5;&#x8D44;&#x5347;&#x5E8F;&#x6392;&#x5E8F;&#xFF08;&#x81EA;&#x7136;&#x6392;&#x5E8F;&#xFF09;
        List<string> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName).collect(Collectors.toList());
        // &#x6309;&#x5DE5;&#x8D44;&#x5012;&#x5E8F;&#x6392;&#x5E8F;
        List<string> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed()).map(Person::getName).collect(Collectors.toList());
        // &#x5148;&#x6309;&#x5DE5;&#x8D44;&#x518D;&#x6309;&#x5E74;&#x9F84;&#x5347;&#x5E8F;&#x6392;&#x5E8F;
        List<string> newList3 = personList.stream().sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName).collect(Collectors.toList());
        // &#x5148;&#x6309;&#x5DE5;&#x8D44;&#x518D;&#x6309;&#x5E74;&#x9F84;&#x81EA;&#x5B9A;&#x4E49;&#x6392;&#x5E8F;&#xFF08;&#x964D;&#x5E8F;&#xFF09;
        List<string> newList4 = personList.stream().sorted((p1, p2) -> {
            if (p1.getSalary().equals(p2.getSalary())) {
                return p2.getAge() - p1.getAge();
            } else {
                return p2.getSalary() - p1.getSalary();
            }
        }).map(Person::getName).collect(Collectors.toList());

        System.out.println("&#x6309;&#x5DE5;&#x8D44;&#x5347;&#x5E8F;&#x6392;&#x5E8F;&#xFF1A;" + newList);
        System.out.println("&#x6309;&#x5DE5;&#x8D44;&#x964D;&#x5E8F;&#x6392;&#x5E8F;&#xFF1A;" + newList2);
        System.out.println("&#x5148;&#x6309;&#x5DE5;&#x8D44;&#x518D;&#x6309;&#x5E74;&#x9F84;&#x5347;&#x5E8F;&#x6392;&#x5E8F;&#xFF1A;" + newList3);
        System.out.println("&#x5148;&#x6309;&#x5DE5;&#x8D44;&#x518D;&#x6309;&#x5E74;&#x9F84;&#x81EA;&#x5B9A;&#x4E49;&#x964D;&#x5E8F;&#x6392;&#x5E8F;&#xFF1A;" + newList4);
    }</string></string></string></string></person>

结果:

Java8新特性之Stream流(含具体案例)

8.提取/组合

流也可以进行合并、去重、限制、跳过等操作。

    public static void main(String[] args) {

        String[] arr1 = {"a", "b", "c", "d"};
        String[] arr2 = {"d", "e", "f", "g"};

        Stream<string> stream1 = Stream.of(arr1);
        Stream<string> stream2 = Stream.of(arr2);
        // concat:&#x5408;&#x5E76;&#x4E24;&#x4E2A;&#x6D41; distinct&#xFF1A;&#x53BB;&#x91CD;
        List<string> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());
        // limit&#xFF1A;&#x9650;&#x5236;&#x4ECE;&#x6D41;&#x4E2D;&#x83B7;&#x5F97;&#x524D;n&#x4E2A;&#x6570;&#x636E;
        List<integer> collect = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
        // skip&#xFF1A;&#x8DF3;&#x8FC7;&#x524D;n&#x4E2A;&#x6570;&#x636E;
        List<integer> collect2 = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList());

        System.out.println("&#x6D41;&#x5408;&#x5E76;&#xFF1A;" + newList);
        System.out.println("limit&#xFF1A;" + collect);
        System.out.println("skip&#xFF1A;" + collect2);
    }</integer></integer></string></string></string>

结果:

Java8新特性之Stream流(含具体案例)

Original: https://www.cnblogs.com/wyj-java/p/16792404.html
Author: Javaの甘乃迪
Title: Java8新特性之Stream流(含具体案例)



相关阅读

Title: 迟来的2021年个人总结

  • 弱项:非科班出身,年龄过35岁,之前没有进入过程序员行业。
  • 优势:英语很好,喜欢挑战,热爱Coding。

流水帐

  • 学习
  • 找工作
  • 工作
  • 换工作
  • 工作/加班
  • 年终

探索过的技术

  • Python
  • FastAPI
  • Flask
  • Flask Smorest
  • Django
  • Django Rest Framework
  • Modules
    • Pandas
    • SQL Alchemy
  • Go

  • Nginx

  • Docker
  • Docker Compose
  • K8S

  • Vue

  • JS

  • MySQL

  • Git
  • 微信支付
  • 云存储
  • Linux
  • Shell
  • 流程图
  • SDD文档
  • Vim
  • Pycharm
  • VS code
  • Postman
  • Jira
  • Lanhu
  • Figma

几件小事

记得开始时,说是要招两个Python开发,”入职前交谈”也确实是两个项目分配好,我被分配去做一个全新的项目。当时想着有不清楚的还可以问一下同事,挺开心的。正式入职才发现,另一个人没有入职,只有我一个人入职,然后技术领导还不在现场办公,几乎每周只过来一次。我一个刚入行的新人,就这样几乎单枪匹马地就踏入了战场。

首先,因为新项目老板已经定好开发方向和基本的逻辑,前端也基本上是待命状态,所以基本都在等我的设计和代码了。本来,以为摆在我面前的难题是:

  • 如何做概要设计和详细设计?
  • 如何做数据库设计?
  • FastAPI是啥?
  • 接口是如何工作的?
  • Docker是什么?如何配置?

可是,实际的情况是,我自己模仿着写的项目基本框架代码都跑不起来,不断的报”Import Error”,也就是包导入错误, 我不断的搜索网络上的答案,StackOverflow中的方法也不断尝试,但是不更改框架中代码的位置,就始终无法正确运行。折磨了我1天多后,恰巧技术领导第2天到办公室,我心虚的询问(对,是心虚,而非虚心)这个问题的解决方案,他调试了一下,展现了问题出现的原因。后来,不管是数据库设计,还是Docker配置,我都陆陆续续有问问题,导致第2周被谈话,基本内容就是:本来招你是来解决问题的,现在到好,除了问题本身,还需要解决你提出的新的问题,那不变成了技术领导的新的负担了吗?

自那次谈话后,碰到任何新的问题,我都是自己来解决。速度慢一点没关系,在脑袋中想象着代码运行的每一步,想象着每一步可能出的问题,最后一一将问题解决,不会的就去学,Docker,Nginx,FastAPI等等,看不懂中文就看英文,看不懂文字就看视频,已经会的查找最优方案,最终一步步将需求实现了。

(挖坑,有心情再来补)

(挖坑,有心情再来补)

(挖坑,有心情再来补)

好了,假装自己写完了,今天先到这,休息一下,祝福自己新的一年接受更大的技术挑战,并且圆满完成任务。

Original: https://blog.csdn.net/weixin_46728614/article/details/122802786
Author: weixin_46728614
Title: 迟来的2021年个人总结

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/363499/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

最近整理资源【免费获取】:   👉 程序员最新必读书单  | 👏 互联网各方向面试题下载 | ✌️计算机核心资源汇总