<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          20 個(gè)實(shí)例玩轉(zhuǎn) Java 8 Stream,寫(xiě)的太好了!

          共 30937字,需瀏覽 62分鐘

           ·

          2021-09-06 08:17

          上一篇:深夜看了張一鳴的微博,讓我越想越后怕



          先貼上幾個(gè)案例,水平高超的同學(xué)可以挑戰(zhàn)一下:

          1. 從員工集合中篩選出salary大于8000的員工,并放置到新的集合里。

          2. 統(tǒng)計(jì)員工的最高薪資、平均薪資、薪資之和。

          3. 將員工按薪資從高到低排序,同樣薪資者年齡小者在前。

          4. 將員工按性別分類,將員工按性別和地區(qū)分類,將員工按薪資是否高于8000分為兩部分。

          用傳統(tǒng)的迭代處理也不是很難,但代碼就顯得冗余了,跟Stream相比高下立判。

          1 Stream概述

          Java 8 是一個(gè)非常成功的版本,這個(gè)版本新增的Stream,配合同版本出現(xiàn)的 Lambda ,給我們操作集合(Collection)提供了極大的便利。

          那么什么是Stream?

          Stream將要處理的元素集合看作一種流,在流的過(guò)程中,借助Stream API對(duì)流中的元素進(jìn)行操作,比如:篩選、排序、聚合等。

          Stream可以由數(shù)組或集合創(chuàng)建,對(duì)流的操作分為兩種:

          1. 中間操作,每次返回一個(gè)新的流,可以有多個(gè)。
          2. 終端操作,每個(gè)流只能進(jìn)行一次終端操作,終端操作結(jié)束后流無(wú)法再次使用。終端操作會(huì)產(chǎn)生一個(gè)新的集合或值。
          另外,Stream有幾個(gè)特性:
          1. stream不存儲(chǔ)數(shù)據(jù),而是按照特定的規(guī)則對(duì)數(shù)據(jù)進(jìn)行計(jì)算,一般會(huì)輸出結(jié)果。
          2. stream不會(huì)改變數(shù)據(jù)源,通常情況下會(huì)產(chǎn)生一個(gè)新的集合或一個(gè)值。
          3. stream具有延遲執(zhí)行特性,只有調(diào)用終端操作時(shí),中間操作才會(huì)執(zhí)行。

          2 Stream的創(chuàng)建

          Stream可以通過(guò)集合數(shù)組創(chuàng)建。

          1、通過(guò) java.util.Collection.stream() 方法用集合創(chuàng)建流

          List<String> list = Arrays.asList("a""b""c");
          // 創(chuàng)建一個(gè)順序流
          Stream<String> stream = list.stream();
          // 創(chuàng)建一個(gè)并行流
          Stream<String> parallelStream = list.parallelStream();
          2、使用java.util.Arrays.stream(T[] array)方法用數(shù)組創(chuàng)建流
          int[] array={1,3,5,6,8};
          IntStream stream = Arrays.stream(array);
          3、使用Stream的靜態(tài)方法:of()、iterate()、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); // 0 2 4 6 8 10

          Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
          stream3.forEach(System.out::println);
          輸出結(jié)果:

          0 3 6 9 0.6796156909271994 0.1914314208854283 0.8116932592396652

          streamparallelStream的簡(jiǎn)單區(qū)分: stream是順序流,由主線程按順序?qū)α鲌?zhí)行操作,而parallelStream是并行流,內(nèi)部以多線程并行執(zhí)行的方式對(duì)流進(jìn)行操作,但前提是流中的數(shù)據(jù)處理沒(méi)有順序要求。例如篩選集合中的奇數(shù),兩者的處理不同之處:

          如果流中的數(shù)據(jù)量足夠大,并行流可以加快處速度。

          除了直接創(chuàng)建并行流,還可以通過(guò)parallel()把順序流轉(zhuǎn)換成并行流:

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

          3 Stream的使用

          在使用stream之前,先理解一個(gè)概念:Optional 。

          Optional類是一個(gè)可以為null的容器對(duì)象。如果值存在則isPresent()方法會(huì)返回true,調(diào)用get()方法會(huì)返回該對(duì)象。更詳細(xì)說(shuō)明請(qǐng)見(jiàn):菜鳥(niǎo)教程Java 8 Optional類

          接下來(lái),大批代碼向你襲來(lái)!我將用20個(gè)案例將Stream的使用整得明明白白,只要跟著敲一遍代碼,就能很好地掌握。

          案例使用的員工類

          這是后面案例中使用的員工類:
          List<Person> personList = new ArrayList<Person>();
          personList.add(new Person("Tom", 8900, "male""New York"));
          personList.add(new Person("Jack", 7000, "male""Washington"));
          personList.add(new Person("Lily", 7800, "female""Washington"));
          personList.add(new Person("Anni", 8200, "female""New York"));
          personList.add(new Person("Owen", 9500, "male""New York"));
          personList.add(new Person("Alisa", 7900, "female""New York"));

          class Person {
           private String name;  // 姓名
           private int salary; // 薪資
           private int age; // 年齡
           private String sex; //性別
           private String area;  // 地區(qū)

           // 構(gòu)造方法
           public Person(String name, int salary, int age,String sex,String area) {
            this.name = name;
            this.salary = salary;
            this.age = age;
            this.sex = sex;
            this.area = area;
           }
           // 省略了get和set,請(qǐng)自行添加

          }

          3.1 遍歷/匹配(foreach/find/match)

          Stream也是支持類似集合的遍歷和匹配元素的,只是Stream中的元素是以Optional類型存在的。Stream的遍歷、匹配非常簡(jiǎn)單。另外,Java 8 系列教程和示例全部整理好了,微信搜索互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)發(fā)送:2T,可以在線閱讀。
          // import已省略,請(qǐng)自行添加,后面代碼亦是

          public class StreamTest {
           public static void main(String[] args) {
                  List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);

                  // 遍歷輸出符合條件的元素
                  list.stream().filter(x -> x > 6).forEach(System.out::println);
                  // 匹配第一個(gè)
                  Optional<Integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
                  // 匹配任意(適用于并行流)
                  Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
                  // 是否包含符合特定條件的元素
                  boolean anyMatch = list.stream().anyMatch(x -> x < 6);
                  System.out.println("匹配第一個(gè)值:" + findFirst.get());
                  System.out.println("匹配任意一個(gè)值:" + findAny.get());
                  System.out.println("是否存在大于6的值:" + anyMatch);
              }
          }

          3.2 篩選(filter)

          篩選,是按照一定的規(guī)則校驗(yàn)流中的元素,將符合條件的元素提取到新的流中的操作。

          案例一:篩選出Integer集合中大于7的元素,并打印出來(lái)

          public class StreamTest {
           public static void main(String[] args) {
            List<Integer> list = Arrays.asList(6, 7, 3, 8, 1, 2, 9);
            Stream<Integer> stream = list.stream();
            stream.filter(x -> x > 7).forEach(System.out::println);
           }
          }

          預(yù)期結(jié)果:

          8 9

          案例二:篩選員工中工資高于8000的人,并形成新的集合。 形成新集合依賴collect(收集),后文有詳細(xì)介紹。

          public class StreamTest {
           public static void main(String[] args) {
            List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 23, "male""New York"));
            personList.add(new Person("Jack", 7000, 25, "male""Washington"));
            personList.add(new Person("Lily", 7800, 21, "female""Washington"));
            personList.add(new Person("Anni", 8200, 24, "female""New York"));
            personList.add(new Person("Owen", 9500, 25, "male""New York"));
            personList.add(new Person("Alisa", 7900, 26, "female""New York"));

            List<String> fiterList = personList.stream().filter(x -> x.getSalary() > 8000).map(Person::getName)
              .collect(Collectors.toList());
            System.out.print("高于8000的員工姓名:" + fiterList);
           }
          }
          運(yùn)行結(jié)果:

          高于8000的員工姓名:[Tom, Anni, Owen]

          3.3 聚合(max/min/count)

          max、min、count這些字眼你一定不陌生,沒(méi)錯(cuò),在mysql中我們常用它們進(jìn)行數(shù)據(jù)統(tǒng)計(jì)。Java stream中也引入了這些概念和用法,極大地方便了我們對(duì)集合、數(shù)組的數(shù)據(jù)統(tǒng)計(jì)工作。

          案例一:獲取String集合中最長(zhǎng)的元素。

          public class StreamTest {
           public static void main(String[] args) {
            List<String> list = Arrays.asList("adnm""admmt""pot""xbangd""weoujgsd");

            Optional<String> max = list.stream().max(Comparator.comparing(String::length));
            System.out.println("最長(zhǎng)的字符串:" + max.get());
           }
          }

          輸出結(jié)果:

          最長(zhǎng)的字符串:weoujgsd

          案例二:獲取Integer集合中的最大值。

          public class StreamTest {
           public static void main(String[] args) {
            List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 6);

            // 自然排序
            Optional<Integer> max = list.stream().max(Integer::compareTo);
            // 自定義排序
            Optional<Integer> max2 = list.stream().max(new Comparator<Integer>() {
             @Override
             public int compare(Integer o1, Integer o2) {
              return o1.compareTo(o2);
             }
            });
            System.out.println("自然排序的最大值:" + max.get());
            System.out.println("自定義排序的最大值:" + max2.get());
           }
          }
          輸出結(jié)果:

          自然排序的最大值:11 自定義排序的最大值:11

          案例三:獲取員工工資最高的人。

          public class StreamTest {
           public static void main(String[] args) {
            List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 23, "male""New York"));
            personList.add(new Person("Jack", 7000, 25, "male""Washington"));
            personList.add(new Person("Lily", 7800, 21, "female""Washington"));
            personList.add(new Person("Anni", 8200, 24, "female""New York"));
            personList.add(new Person("Owen", 9500, 25, "male""New York"));
            personList.add(new Person("Alisa", 7900, 26, "female""New York"));

            Optional<Person> max = personList.stream().max(Comparator.comparingInt(Person::getSalary));
            System.out.println("員工工資最大值:" + max.get().getSalary());
           }
          }
          輸出結(jié)果:

          員工工資最大值:9500

          案例四:計(jì)算Integer集合中大于6的元素的個(gè)數(shù)。

          import java.util.Arrays;
          import java.util.List;

          public class StreamTest {
           public static void main(String[] args) {
            List<Integer> list = Arrays.asList(7, 6, 4, 8, 2, 11, 9);

            long count = list.stream().filter(x -> x > 6).count();
            System.out.println("list中大于6的元素個(gè)數(shù):" + count);
           }
          }
          輸出結(jié)果:

          list中大于6的元素個(gè)數(shù):4

          3.4 映射(map/flatMap)

          映射,可以將一個(gè)流的元素按照一定的映射規(guī)則映射到另一個(gè)流中。分為mapflatMap
          • map:接收一個(gè)函數(shù)作為參數(shù),該函數(shù)會(huì)被應(yīng)用到每個(gè)元素上,并將其映射成一個(gè)新的元素。

          • flatMap:接收一個(gè)函數(shù)作為參數(shù),將流中的每個(gè)值都換成另一個(gè)流,然后把所有流連接成一個(gè)流。

          案例一:英文字符串?dāng)?shù)組的元素全部改為大寫(xiě)。整數(shù)數(shù)組每個(gè)元素+3。

          public class StreamTest {
           public static void main(String[] args) {
            String[] strArr = { "abcd""bcdd""defde""fTr" };
            List<String> strList = Arrays.stream(strArr).map(String::toUpperCase).collect(Collectors.toList());

            List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);
            List<Integer> intListNew = intList.stream().map(x -> x + 3).collect(Collectors.toList());

            System.out.println("每個(gè)元素大寫(xiě):" + strList);
            System.out.println("每個(gè)元素+3:" + intListNew);
           }
          }
          輸出結(jié)果:

          每個(gè)元素大寫(xiě):[ABCD, BCDD, DEFDE, FTR] 每個(gè)元素+3:[4, 6, 8, 10, 12, 14]


          案例二:將員工的薪資全部增加1000。

          public class StreamTest {
           public static void main(String[] args) {
            List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 23, "male""New York"));
            personList.add(new Person("Jack", 7000, 25, "male""Washington"));
            personList.add(new Person("Lily", 7800, 21, "female""Washington"));
            personList.add(new Person("Anni", 8200, 24, "female""New York"));
            personList.add(new Person("Owen", 9500, 25, "male""New York"));
            personList.add(new Person("Alisa", 7900, 26, "female""New York"));

            // 不改變?cè)瓉?lái)員工集合的方式
            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("一次改動(dòng)前:" + personList.get(0).getName() + "-->" + personList.get(0).getSalary());
            System.out.println("一次改動(dòng)后:" + personListNew.get(0).getName() + "-->" + personListNew.get(0).getSalary());

            // 改變?cè)瓉?lái)員工集合的方式
            List<Person> personListNew2 = personList.stream().map(person -> {
             person.setSalary(person.getSalary() + 10000);
             return person;
            }).collect(Collectors.toList());
            System.out.println("二次改動(dòng)前:" + personList.get(0).getName() + "-->" + personListNew.get(0).getSalary());
            System.out.println("二次改動(dòng)后:" + personListNew2.get(0).getName() + "-->" + personListNew.get(0).getSalary());
           }
          }
          輸出結(jié)果:

          一次改動(dòng)前:Tom–>8900 一次改動(dòng)后:Tom–>18900 二次改動(dòng)前:Tom–>18900 二次改動(dòng)后:Tom–>18900

          案例三:將兩個(gè)字符數(shù)組合并成一個(gè)新的字符數(shù)組。

          public class StreamTest {
           public static void main(String[] args) {
            List<String> list = Arrays.asList("m,k,l,a""1,3,5,7");
            List<String> listNew = list.stream().flatMap(s -> {
             // 將每個(gè)元素轉(zhuǎn)換成一個(gè)stream
             String[] split = s.split(",");
             Stream<String> s2 = Arrays.stream(split);
             return s2;
            }).collect(Collectors.toList());

            System.out.println("處理前的集合:" + list);
            System.out.println("處理后的集合:" + listNew);
           }
          }
          輸出結(jié)果:

          處理前的集合:[m-k-l-a, 1-3-5] 處理后的集合:[m, k, l, a, 1, 3, 5]

          3.5 歸約(reduce)

          歸約,也稱縮減,顧名思義,是把一個(gè)流縮減成一個(gè)值,能實(shí)現(xiàn)對(duì)集合求和、求乘積和求最值操作。

          案例一:求Integer集合的元素之和、乘積和最大值。

          public class StreamTest {
           public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
            // 求和方式1
            Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
            // 求和方式2
            Optional<Integer> sum2 = list.stream().reduce(Integer::sum);
            // 求和方式3
            Integer sum3 = list.stream().reduce(0, Integer::sum);

            // 求乘積
            Optional<Integer> product = list.stream().reduce((x, y) -> x * y);

            // 求最大值方式1
            Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);
            // 求最大值寫(xiě)法2
            Integer max2 = list.stream().reduce(1, Integer::max);

            System.out.println("list求和:" + sum.get() + "," + sum2.get() + "," + sum3);
            System.out.println("list求積:" + product.get());
            System.out.println("list求和:" + max.get() + "," + max2);
           }
          }

          輸出結(jié)果:

          list求和:29,29,29 list求積:2112 list求和:11,11

          案例二:求所有員工的工資之和和最高工資。

          public class StreamTest {
           public static void main(String[] args) {
            List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 23, "male""New York"));
            personList.add(new Person("Jack", 7000, 25, "male""Washington"));
            personList.add(new Person("Lily", 7800, 21, "female""Washington"));
            personList.add(new Person("Anni", 8200, 24, "female""New York"));
            personList.add(new Person("Owen", 9500, 25, "male""New York"));
            personList.add(new Person("Alisa", 7900, 26, "female""New York"));

            // 求工資之和方式1:
            Optional<Integer> sumSalary = personList.stream().map(Person::getSalary).reduce(Integer::sum);
            // 求工資之和方式2:
            Integer sumSalary2 = personList.stream().reduce(0, (sum, p) -> sum += p.getSalary(),
              (sum1, sum2) -> sum1 + sum2);
            // 求工資之和方式3:
            Integer sumSalary3 = personList.stream().reduce(0, (sum, p) -> sum += p.getSalary(), Integer::sum);

            // 求最高工資方式1:
            Integer maxSalary = personList.stream().reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(),
              Integer::max);
            // 求最高工資方式2:
            Integer maxSalary2 = personList.stream().reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(),
              (max1, max2) -> max1 > max2 ? max1 : max2);

            System.out.println("工資之和:" + sumSalary.get() + "," + sumSalary2 + "," + sumSalary3);
            System.out.println("最高工資:" + maxSalary + "," + maxSalary2);
           }
          }
          輸出結(jié)果:

          工資之和:49300,49300,49300 最高工資:9500,9500

          3.6 收集(collect)

          collect,收集,可以說(shuō)是內(nèi)容最繁多、功能最豐富的部分了。從字面上去理解,就是把一個(gè)流收集起來(lái),最終可以是收集成一個(gè)值也可以收集成一個(gè)新的集合。

          collect主要依賴java.util.stream.Collectors類內(nèi)置的靜態(tài)方法。

          3.6.1 歸集(toList/toSet/toMap)

          因?yàn)榱鞑淮鎯?chǔ)數(shù)據(jù),那么在流中的數(shù)據(jù)完成處理后,需要將流中的數(shù)據(jù)重新歸集到新的集合里。toListtoSettoMap比較常用,另外還有toCollection、toConcurrentMap等復(fù)雜一些的用法。

          下面用一個(gè)案例演示toListtoSettoMap

          public class StreamTest {
           public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1, 6, 3, 4, 6, 7, 9, 6, 20);
            List<Integer> listNew = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
            Set<Integer> set = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());

            List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 23, "male""New York"));
            personList.add(new Person("Jack", 7000, 25, "male""Washington"));
            personList.add(new Person("Lily", 7800, 21, "female""Washington"));
            personList.add(new Person("Anni", 8200, 24, "female""New York"));

            Map<?, Person> map = personList.stream().filter(p -> p.getSalary() > 8000)
              .collect(Collectors.toMap(Person::getName, p -> p));
            System.out.println("toList:" + listNew);
            System.out.println("toSet:" + set);
            System.out.println("toMap:" + map);
           }
          }
          運(yùn)行結(jié)果:

          toList:[6, 4, 6, 6, 20] toSet:[4, 20, 6] toMap:{Tom=mutest.Person@5fd0d5ae, Anni=mutest.Person@2d98a335}

          3.6.2 統(tǒng)計(jì)(count/averaging)

          Collectors提供了一系列用于數(shù)據(jù)統(tǒng)計(jì)的靜態(tài)方法:

          • 計(jì)數(shù):count
          • 平均值:averagingInt、averagingLongaveragingDouble
          • 最值:maxBy、minBy
          • 求和:summingInt、summingLongsummingDouble
          • 統(tǒng)計(jì)以上所有:summarizingInt、summarizingLong、summarizingDouble

          案例:統(tǒng)計(jì)員工人數(shù)、平均工資、工資總額、最高工資。

          public class StreamTest {
           public static void main(String[] args) {
            List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 23, "male""New York"));
            personList.add(new Person("Jack", 7000, 25, "male""Washington"));
            personList.add(new Person("Lily", 7800, 21, "female""Washington"));

            // 求總數(shù)
            Long count = personList.stream().collect(Collectors.counting());
            // 求平均工資
            Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
            // 求最高工資
            Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
            // 求工資之和
            Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
            // 一次性統(tǒng)計(jì)所有信息
            DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));

            System.out.println("員工總數(shù):" + count);
            System.out.println("員工平均工資:" + average);
            System.out.println("員工工資總和:" + sum);
            System.out.println("員工工資所有統(tǒng)計(jì):" + collect);
           }
          }

          運(yùn)行結(jié)果:

          員工總數(shù):3 員工平均工資:7900.0 員工工資總和:23700 員工工資所有統(tǒng)計(jì):DoubleSummaryStatistics{count=3, sum=23700.000000,min=7000.000000, average=7900.000000, max=8900.000000}

          3.6.3 分組(partitioningBy/groupingBy)

          • 分區(qū):將stream按條件分為兩個(gè)Map,比如員工按薪資是否高于8000分為兩部分。
          • 分組:將集合分為多個(gè)Map,比如員工按性別分組。有單級(jí)分組和多級(jí)分組。

          案例:將員工按薪資是否高于8000分為兩部分;將員工按性別和地區(qū)分組

          public class StreamTest {
           public static void main(String[] args) {
            List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, "male""New York"));
            personList.add(new Person("Jack", 7000, "male""Washington"));
            personList.add(new Person("Lily", 7800, "female""Washington"));
            personList.add(new Person("Anni", 8200, "female""New York"));
            personList.add(new Person("Owen", 9500, "male""New York"));
            personList.add(new Person("Alisa", 7900, "female""New York"));

            // 將員工按薪資是否高于8000分組
                  Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
                  // 將員工按性別分組
                  Map<String, List<Person>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));
                  // 將員工先按性別分組,再按地區(qū)分組
                  Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
                  System.out.println("員工按薪資是否大于8000分組情況:" + part);
                  System.out.println("員工按性別分組情況:" + group);
                  System.out.println("員工按性別、地區(qū):" + group2);
           }
          }

          輸出結(jié)果:

          員工按薪資是否大于8000分組情況:{false=[mutest.Person@2d98a335, mutest.Person@16b98e56, mutest.Person@7ef20235], true=[mutest.Person@27d6c5e0, mutest.Person@4f3f5b24, mutest.Person@15aeb7ab]}  

          員工按性別分組情況:{female=[mutest.Person@16b98e56, mutest.Person@4f3f5b24, mutest.Person@7ef20235], male=[mutest.Person@27d6c5e0, mutest.Person@2d98a335, mutest.Person@15aeb7ab]}  

          員工按性別、地區(qū):{female={New York=[mutest.Person@4f3f5b24, mutest.Person@7ef20235], Washington=[mutest.Person@16b98e56]}, male={New York=[mutest.Person@27d6c5e0, mutest.Person@15aeb7ab], Washington=[mutest.Person@2d98a335]}}  

          3.6.4 接合(joining)

          joining可以將stream中的元素用特定的連接符(沒(méi)有的話,則直接連接)連接成一個(gè)字符串。

          public class StreamTest {
           public static void main(String[] args) {
            List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 23, "male""New York"));
            personList.add(new Person("Jack", 7000, 25, "male""Washington"));
            personList.add(new Person("Lily", 7800, 21, "female""Washington"));

            String names = personList.stream().map(p -> p.getName()).collect(Collectors.joining(","));
            System.out.println("所有員工的姓名:" + names);
            List<String> list = Arrays.asList("A""B""C");
            String string = list.stream().collect(Collectors.joining("-"));
            System.out.println("拼接后的字符串:" + string);
           }
          }

          運(yùn)行結(jié)果:

          所有員工的姓名:Tom,Jack,Lily 拼接后的字符串:A-B-C

          3.6.5 歸約(reducing)

          Collectors類提供的reducing方法,相比于stream本身的reduce方法,增加了對(duì)自定義歸約的支持。

          public class StreamTest {
           public static void main(String[] args) {
            List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 23, "male""New York"));
            personList.add(new Person("Jack", 7000, 25, "male""Washington"));
            personList.add(new Person("Lily", 7800, 21, "female""Washington"));

            // 每個(gè)員工減去起征點(diǎn)后的薪資之和(這個(gè)例子并不嚴(yán)謹(jǐn),但一時(shí)沒(méi)想到好的例子)
            Integer sum = personList.stream().collect(Collectors.reducing(0, Person::getSalary, (i, j) -> (i + j - 5000)));
            System.out.println("員工扣稅薪資總和:" + sum);

            // stream的reduce
            Optional<Integer> sum2 = personList.stream().map(Person::getSalary).reduce(Integer::sum);
            System.out.println("員工薪資總和:" + sum2.get());
           }
          }

          運(yùn)行結(jié)果:

          員工扣稅薪資總和:8700 員工薪資總和:23700

          3.7 排序(sorted)

          sorted,中間操作。有兩種排序:

          案例:將員工按工資由高到低(工資一樣則按年齡由大到?。┡判?/strong>

          public class StreamTest {
           public static void main(String[] args) {
            List<Person> personList = new ArrayList<Person>();

            personList.add(new Person("Sherry", 9000, 24, "female""New York"));
            personList.add(new Person("Tom", 8900, 22, "male""Washington"));
            personList.add(new Person("Jack", 9000, 25, "male""Washington"));
            personList.add(new Person("Lily", 8800, 26, "male""New York"));
            personList.add(new Person("Alisa", 9000, 26, "female""New York"));

            // 按工資升序排序(自然排序)
            List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName)
              .collect(Collectors.toList());
            // 按工資倒序排序
            List<String> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
              .map(Person::getName).collect(Collectors.toList());
            // 先按工資再按年齡升序排序
            List<String> newList3 = personList.stream()
              .sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName)
              .collect(Collectors.toList());
            // 先按工資再按年齡自定義排序(降序)
            List<String> newList4 = personList.stream().sorted((p1, p2) -> {
             if (p1.getSalary() == p2.getSalary()) {
              return p2.getAge() - p1.getAge();
             } else {
              return p2.getSalary() - p1.getSalary();
             }
            }).map(Person::getName).collect(Collectors.toList());

            System.out.println("按工資升序排序:" + newList);
            System.out.println("按工資降序排序:" + newList2);
            System.out.println("先按工資再按年齡升序排序:" + newList3);
            System.out.println("先按工資再按年齡自定義降序排序:" + newList4);
           }
          }

          運(yùn)行結(jié)果:

          按工資自然排序:[Lily, Tom, Sherry, Jack, Alisa] 按工資降序排序:[Sherry, Jack, Alisa,Tom, Lily] 先按工資再按年齡自然排序:[Sherry, Jack, Alisa, Tom, Lily] 先按工資再按年齡自定義降序排序:[Alisa, Jack, Sherry, Tom, Lily]

          3.8 提取/組合

          流也可以進(jìn)行合并、去重、限制、跳過(guò)等操作。

          public class StreamTest {
           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:合并兩個(gè)流 distinct:去重
            List<String> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());
            // limit:限制從流中獲得前n個(gè)數(shù)據(jù)
            List<Integer> collect = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
            // skip:跳過(guò)前n個(gè)數(shù)據(jù)
            List<Integer> collect2 = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList());

            System.out.println("流合并:" + newList);
            System.out.println("limit:" + collect);
            System.out.println("skip:" + collect2);
           }
          }

          運(yùn)行結(jié)果:

          流合并:[a, b, c, d, e, f, g] limit:[1, 3, 5, 7, 9, 11, 13, 15, 17, 19] skip:[3, 5, 7, 9, 11]

          4 Stream源碼解讀

          這部分等有時(shí)間慢慢分解吧。

          好,以上就是全部?jī)?nèi)容,能堅(jiān)持看到這里,你一定很有收獲,那么動(dòng)一動(dòng)拿offer的小手,點(diǎn)個(gè)贊再走吧。

          原文鏈接:https://blog.csdn.net/mu_wind/article/details/109516995

          感謝您的閱讀,也歡迎您發(fā)表關(guān)于這篇文章的任何建議,關(guān)注我,技術(shù)不迷茫!小編到你上高速。

              · END ·
          最后,關(guān)注公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)回復(fù):2T,可以獲取我整理的 Java 系列面試題和答案,非常齊全。


          正文結(jié)束


          推薦閱讀 ↓↓↓

          1.不認(rèn)命,從10年流水線工人,到谷歌上班的程序媛,一位湖南妹子的勵(lì)志故事

          2.如何才能成為優(yōu)秀的架構(gòu)師?

          3.從零開(kāi)始搭建創(chuàng)業(yè)公司后臺(tái)技術(shù)棧

          4.程序員一般可以從什么平臺(tái)接私活?

          5.37歲程序員被裁,120天沒(méi)找到工作,無(wú)奈去小公司,結(jié)果懵了...

          6.IntelliJ IDEA 2019.3 首個(gè)最新訪問(wèn)版本發(fā)布,新特性搶先看

          7.這封“領(lǐng)導(dǎo)痛批95后下屬”的郵件,句句扎心!

          8.15張圖看懂瞎忙和高效的區(qū)別!

          一個(gè)人學(xué)習(xí)、工作很迷茫?


          點(diǎn)擊「閱讀原文」加入我們的小圈子!

          瀏覽 55
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久大香蕉艹逼 | 欧美成人精品欧美一级 | 在线视频中文字幕一区 | 免费视频久久久 | 女人18片毛片120分钟 |