學習java8這篇文章就夠了

目錄

本文分3部分java

java8-基礎json

主要講述java8的一些基礎概念及用法。包括:Optional類,Lambda表達式,Stream接口。c#

java8-進階bash

主要講述java8的一些進階用法。包括:Function接口,自定義Stream接口。多線程

java8-實踐併發

主要講述java8的用法的一些比較特別的實踐用法。app

點一點連接,支持一波吃飯,http://aliyun.guan2ye.com/dom

基礎

(一)optional類

  • 建立一個空Optional對象ide

    輸出的是一個空的optional對象函數

    Optional<String> optional = Optional.empty();
    System.out.println(optional);
    ##:Optional.empty
    複製代碼
  • 建立一個非空Optional對象

    若是personnull,將會當即拋出,而不是訪問person的屬性時得到一個潛在的錯誤

    Person person = new Person("xu","hua");
    Optional<Person> optional2 = Optional.of(person);
    System.out.println(optional2);
    System.out.println(optional2.get());
    System.out.println(optional2.get().firstName);
    ##:Optional[xuhua]
        xuhua
        xu
    複製代碼
  • 判斷對象是否存在

    System.out.println(optional.isPresent());
    System.out.println(optional2.isPresent());
    ##:false
       true
    複製代碼
  • 若是Optional爲空返回默認值

    System.out.println(optional.orElse("fallback"));
    optional.ifPresent(System.out::println);
    ##:fallback
        xuhua
    複製代碼

(二)Lambda表達式

  • Lambda表達式的使用

    java8之前的字符串排列,建立一個匿名的比較器對象Comparator而後將其傳遞給sort方法

    List<String> names= Arrays.asList("peter", "anna", "mike", "xenia");
    Collections.sort(names, new Comparator<String>() {
                @Override
                public int compare(String a, String b) {
                return b.compareTo(a);
            }
        });
    複製代碼

    java8使用lambda表達式就不須要匿名對象了

    Collections.sort(names,(String a,String b)->{return b.compareTo(a);});
    複製代碼

    簡化一下:對於函數體只有一行代碼的,你能夠去掉大括號{}以及return關鍵字

    Collections.sort(names,(String a,String b)->b.compareTo(a));
    複製代碼

    Java編譯器能夠自動推導出參數類型,因此你能夠不用再寫一次類型

    Collections.sort(names, (a, b) -> b.compareTo(a));
    複製代碼
    ##:[xenia, peter, mike, anna]
    複製代碼

    對於null的處理

    List<String> names2 = Arrays.asList("peter", null, "anna", "mike", "xenia");
    names2.sort(Comparator.nullsLast(String::compareTo));
    System.out.println(names2);
    ##:[anna, mike, peter, xenia, null]
    複製代碼
  • 函數式接口,方法,構造器

    每個lambda表達式都對應一個類型,一般是接口類型。

    而「函數式接口」是指僅僅只包含一個抽象方法的接口,每個該類型的lambda表達式都會被匹配到這個抽象方法。

    由於默認方法不算抽象方法,因此你也能夠給你的函數式接口添加默認方法。

    咱們能夠將lambda表達式看成任意只包含一個抽象方法的接口類型,確保你的接口必定達到這個要求,

    你只須要給你的接口添加 @FunctionalInterface 註解,

    編譯器若是發現你標註了這個註解的接口有多於一個抽象方法的時候會報錯的。

    • 函數式接口

      @FunctionalInterface
      public static interface Converter<F, T> {
          T convert(F from);
      }
      /**原始的接口實現*/
      Converter<String, Integer> integerConverter1 = new Converter<String, Integer>() {
          @Override
          public Integer convert(String from) {
              return Integer.valueOf(from);
          }
      };
      
      /**使用lambda表達式實現接口*/
      Converter<String, Integer> integerConverter2 = (from) -> Integer.valueOf(from);
      
      Integer converted1 = integerConverter1.convert("123");
      Integer converted2 = integerConverter2.convert("123");
      System.out.println(converted1);   
      System.out.println(converted2);   
      ##:123
      123
      /**簡寫的lambda表達式*/
      Converter<String, Integer> integerConverter3 = Integer::valueOf;
      Integer converted3 = integerConverter3.convert("123");
      System.out.println(converted3);   
      ##:123
      複製代碼
    • 函數式方法

      static class Something {
          String startsWith(String s) {
              return String.valueOf(s.charAt(0));
          }
      }
      Something something = new Something();
      Converter<String, String> stringConverter = something::startsWith;
      String converted4 = stringConverter.convert("Java");
      System.out.println(converted4);    
      ##:j
      複製代碼
    • 函數式構造器

      Java編譯器會自動根據PersonFactory.create方法的簽名來選擇合適的構造函數。

      public class Person {
          public String firstName;
          public String lastName;
      
          public Person() {
          }
      
          public Person(String firstName, String lastName) {
              this.firstName = firstName;
              this.lastName = lastName;
          }
      
          public String toString(){
              return firstName+lastName;
          }
      }
      複製代碼
      interface PersonFactory<P extends Person> {
          P create(String firstName, String lastName);
      }
      PersonFactory<Person> personFactory = Person::new;
      Person person = personFactory.create("xu", "hua");
      System.out.println(person.toString());
      ##:xuhua
      複製代碼
  • Lambda做用域 點一點連接,支持一波吃飯,http://aliyun.guan2ye.com/

    在lambda表達式中訪問外層做用域和老版本的匿名對象中的方式很類似。

    你能夠直接訪問標記了final的外層局部變量,或者實例的字段以及靜態變量。

    static int outerStaticNum = 10;
    
    int outerNum;
    
    void testScopes() {
        
        /**變量num能夠不用聲明爲final*/
        int num = 1;
    
        /**能夠直接在lambda表達式中訪問外層的局部變量*/
        Lambda2.Converter<Integer, String> stringConverter =
                        (from) -> String.valueOf(from + outerStaticNum+num);
        String convert = stringConverter.convert(2);
        System.out.println(convert);   
        ##:13
        /**可是num必須不可被後面的代碼修改(即隱性的具備final的語義),不然編譯出錯*/
        //num=3;
    
        /**lambda內部對於實例的字段以及靜態變量是便可讀又可寫*/
        Lambda2.Converter<Integer, String> stringConverter2 = (from) -> {
            outerNum = 13;
            return String.valueOf(from + outerNum);
        };
        System.out.println(stringConverter2.convert(2));
        System.out.println("\nBefore:outerNum-->" + outerNum);
        outerNum = 15;
        System.out.println("After:outerNum-->" + outerNum);
        ##:Before:outerNum-->13
           After:outerNum-->15
        
        String[] array = new String[1];
        Lambda2.Converter<Integer, String> stringConverter3 = (from) -> {
            array[0] = "Hi here";
            return String.valueOf(from);
        };
        stringConverter3.convert(23);
        System.out.println("\nBefore:array[0]-->" + array[0]);
        array[0] = "Hi there";
        System.out.println("After:array[0]-->" + array[0]);
        ##:Before:array[0]-->Hi here
           After:array[0]-->Hi there
    }
    複製代碼

(三)Stream類

點一點連接,支持一波吃飯,http://aliyun.guan2ye.com/

java.util.Stream 表示能應用在一組元素上一次執行的操做序列。

Stream 操做分爲中間操做或者最終操做兩種,最終操做返回一特定類型的計算結果,而中間操做返回Stream自己,這樣你就能夠將多個操做依次串起來。

Stream 的建立須要指定一個數據源,好比 java.util.Collection的子類,List或者SetMap不支持。

Stream的操做能夠串行執行或者並行執行。

  • Stream的基本接口

    List<String> stringCollection = new ArrayList<>();
    stringCollection.add("ddd2");
    stringCollection.add("aaa2");
    stringCollection.add("bbb1");
    stringCollection.add("aaa1");
    stringCollection.add("bbb3");
    stringCollection.add("ccc");
    stringCollection.add("bbb2");
    stringCollection.add("ddd1");
    複製代碼
    • Filter 過濾.

      Filter經過一個predicate接口來過濾並只保留符合條件的元素,該操做屬於中間操做,因此咱們能夠在過濾後的結果來應用其餘Stream操做(好比forEach)。

      forEach須要一個函數來對過濾後的元素依次執行。

      forEach是一個最終操做,因此咱們不能在forEach以後來執行其餘Stream操做。

      stringCollection
          .stream()
          .filter((s) -> s.startsWith("a"))
          .forEach(System.out::println);
      複製代碼
    • Sorted 排序.

      Sorted是一箇中間操做,返回的是排序好後的Stream

      若是你不指定一個自定義的Comparator則會使用默認排序.

      stringCollection
         .stream()
         .sorted()
         .forEach(System.out::println);
      System.out.println(stringCollection);//原數據源不會被改變
      複製代碼
    • Map.

      中間操做map會將元素根據指定的Function接口來依次將元素轉成另外的對象.

      stringCollection
          .stream()
          .map(String::toUpperCase)
          .map((s)->s+" space")
          .sorted((a, b) -> b.compareTo(a))
          .forEach(System.out::println);
      複製代碼
    • Match

      Stream提供了多種匹配操做,容許檢測指定的Predicate是否匹配整個Stream

      全部的匹配操做都是最終操做,並返回一個boolean類型的值。

      boolean anyStartsWithA = stringCollection
          .stream()
          .anyMatch((s) -> s.startsWith("a"));
      System.out.println(anyStartsWithA);      // true
      
      boolean allStartsWithA = stringCollection
          .stream()
          .allMatch((s) -> s.startsWith("a"));
      System.out.println(allStartsWithA);      // false
      
      boolean noneStartsWithZ = stringCollection
          .stream()
          .noneMatch((s) -> s.startsWith("z"));
      System.out.println(noneStartsWithZ);      // true
      複製代碼
    • Count

      計數是一個最終操做,返回Stream中元素的個數,返回值類型是long

      long startsWithB = stringCollection
          .stream()
          .filter((s) -> s.startsWith("b"))
          .count();
      System.out.println(startsWithB);    // 3
      複製代碼
    • Reduce

      Reduce是一個最終操做,容許經過指定的函數來說stream中的多個元素規約爲一個元素,規約後的結果是經過Optional接口表示的。

      Optional<String> reduced =
          stringCollection
                  .stream()
                  .sorted()
                  .reduce((s1, s2) -> s1 + "#" + s2);
      
      reduced.ifPresent(System.out::println);
      ##:aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2
      複製代碼
  • 並行stream和串行stream

    • 串行stream

      List<String> values = new ArrayList<>(MAX);
      for (int i = 0; i < MAX; i++) {
          UUID uuid = UUID.randomUUID();
          values.add(uuid.toString());
      }
      
      long t0 = System.nanoTime();
      long count = values.stream().sorted().count();
      System.out.println(count);
      
      long t1 = System.nanoTime();
      long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
      System.out.println(String.format("sequential sort took: %d ms", millis));
      複製代碼
    • 並行stream

      並行stream是在運行時將數據劃分紅了多個塊,而後將數據塊分配給合適的處理器去處理。

      只有當全部塊都處理完成了,纔會執行以後的代碼。

      List<String> values = new ArrayList<>(MAX);
      for (int i = 0; i < MAX; i++) {
          UUID uuid = UUID.randomUUID();
          values.add(uuid.toString());
      }
      
      long t0 = System.nanoTime();
      long count = values.parallelStream().sorted().count();
      System.out.println(count);
      
      long t1 = System.nanoTime();
      long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
      System.out.println(String.format("parallel sort took: %d ms", millis));
      複製代碼

      時間結果比較:

      1000000
      sequential sort took: 717 ms
      1000000
      parallel sort took: 303 ms
      複製代碼
  • IntStream接口

    IntStream接口是stream的一種,繼承了BaseStream接口。

    • range
      IntStream.range(0, 10)
              .forEach(i -> {
                  if (i % 2 == 1) System.out.print(i+" ");
              });
      ##:1 3 5 7 9 
      
      OptionalInt reduced1 =
          IntStream.range(0, 10)
                  .reduce((a, b) -> a + b);
      System.out.println(reduced1.getAsInt());
      
      int reduced2 =
          IntStream.range(0, 10)
                  .reduce(7, (a, b) -> a + b);
      System.out.println(reduced2);
      ##:45
         52
      複製代碼
    • sum
      System.out.println(IntStream.range(0, 10).sum());
      複製代碼
  • Stream的應用

    Map<String, Integer> unsortMap = new HashMap<>();
    unsortMap.put("z", 10);
    unsortMap.put("b", 5);
    unsortMap.put("a", 6);
    unsortMap.put("c", 20);
    unsortMap.put("d", 1);
    unsortMap.put("e", 7);
    unsortMap.put("y", 8);
    unsortMap.put("n", 99);
    unsortMap.put("j", 50);
    unsortMap.put("m", 2);
    unsortMap.put("f", 9);
    複製代碼

    使用stream類來對mapvalue排序

    public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
        Map<K, V> result = new LinkedHashMap<>();
        map.entrySet().parallelStream()
                .sorted((o1, o2) -> (o2.getValue()).compareTo(o1.getValue()))
                .forEachOrdered(x -> result.put(x.getKey(), x.getValue()));
        return result;
    }
    System.out.println(sortByValue(unsortMap));
    ##:{n=99, j=50, c=20, z=10, f=9, y=8, e=7, a=6, b=5, m=2, d=1}
    複製代碼
    List<Object> list = new ArrayList<>();
    JSONObject data1 = new JSONObject();
    data1.put("type", "支出");
    data1.put("money", 500);
    JSONObject data2 = new JSONObject();
    data2.put("type", "收入");
    data2.put("money", 1000);
    JSONObject data3 = new JSONObject();
    data3.put("type", "借貸");
    data3.put("money", 100);
    list.add(data1);
    list.add(data2);
    list.add(data3);
    複製代碼

    使用stream類來處理list``裏面的json`數據

    /**
         * 按money的值來排列json
         */
        list.stream()
                .filter(x -> JSONObject.fromObject(x).containsKey("money"))
                .sorted((b, a) -> Integer.valueOf(JSONObject.fromObject(a).getInt("money")).compareTo(JSONObject.fromObject(b)
                        .getInt("money")))
                .forEach(System.out::println);
        /**
         * 找到最小的money
         */
        Integer min = list.stream()
                .filter(x -> JSONObject.fromObject(x).containsKey("money"))
                .map(x -> JSONObject.fromObject(x).getInt("money"))
                .sorted()
                .findFirst()
                .get();
        System.out.println(min);
        /**
         * 計算type的數目
         */
        Map<String, Integer> type_count = new HashMap<>();
        list.stream()
                .filter(x -> JSONObject.fromObject(x).containsKey("type"))
                .map(x -> JSONObject.fromObject(x).getString("type"))
                .forEach(x -> {
                    if (type_count.containsKey(x)) type_count.put(x, type_count.get(x) + 1);
                    else type_count.put(x, 1);
                });
        System.out.println(type_count.toString());
        ##:
        {"type":"收入","money":1000}
        {"type":"支出","money":500}
        {"type":"借貸","money":100}
        100
        {借貸=1, 收入=1, 支出=1}
    複製代碼

Java8-進階

點一點連接,支持一波吃飯,http://aliyun.guan2ye.com/

函數式接口

只包含一個抽象方法的接口

  • Function<T, R>

    接受一個輸入參數,返回一個結果。

    Function接口包含如下方法:

    定義兩個比較簡單的函數:times2squared

    Function<Integer, Integer> times2 = e -> e * 2;
    Function<Integer, Integer> squared = e -> e * e;
    複製代碼
    • R apply(T t)

      執行函數

      //return 8 - > 4 * 2
      Integer a = times2.apply(4);
      System.out.println(a);
      複製代碼
    • compose

      先執行參數裏面的操做,而後執行調用者

      //return 32 - > 4 ^ 2 * 2
      Integer b = times2.compose(squared).apply(4);
      System.out.println(b);
      複製代碼
    • andThen

      先執行調用者操做,再執行參數操做

      //return 64 - > (4 * 2) ^ 2
      Integer c = times2.andThen(squared).apply(4);
      System.out.println(c);
      複製代碼
    • identity

      老是返回傳入的參數自己

      //return 4
      Integer d = identity.apply(4);
      System.out.println(d);
      複製代碼
  • BiFunction<T, U, R>

    接受輸入兩個參數,返回一個結果

    • R apply(T t, U u)

      BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
      //return 30
      System.out.println(add.apply(10,20));
      複製代碼
  • Supplier<T>

    無參數,返回一個結果。

    • T get()

      Supplier<Integer> get= () -> 10;
      //return 10
      Integer a=get.get();
      複製代碼
  • Consumer<T>

    表明了接受一個輸入參數而且無返回的操做

    • void accept(T t)

      //return void
      Consumer<Integer> accept=x->{};
      複製代碼
  • BiConsumer<T, U>

    表明了一個接受兩個輸入參數的操做,而且不返回任何結果

    • void accept(T t, U u)

      //return void
      BiConsumer<Integer,Integer> accept=(x,y)->{};
      複製代碼
  • BinaryOperator<T> extends BiFunction<T,T,T>

    一個做用於於兩個同類型操做符的操做,而且返回了操做符同類型的結果

    定義了兩個靜態方法:minBy,maxBy

  • Predicate<T>

    接受一個輸入參數,返回一個布爾值結果。

    • test

      Predicate<String> predicate=x->x.startsWith("a");
      //return ture
      System.out.println(predicate.test("abc"));
      複製代碼

Stream接口

  • Collector接口

    Collector是Stream的可變減小操做接口

    Collector<T, A, R>接受三個泛型參數,對可變減小操做的數據類型做相應限制:

    T:輸入元素類型

    A:縮減操做的可變累積類型(一般隱藏爲實現細節)

    R:可變減小操做的結果類型

    Collector接口聲明瞭4個函數,這四個函數一塊兒協調執行以將元素目累積到可變結果容器中,而且能夠選擇地對結果進行最終的變換:

    • Supplier<A> supplier(): 建立新的結果結
    • BiConsumer<A, T> accumulator(): 將元素添加到結果容器
    • BinaryOperator<A> combiner(): 將兩個結果容器合併爲一個結果容器
    • Function<A, R> finisher(): 對結果容器做相應的變換

    在Collector接口的characteristics方法內,能夠對Collector聲明相關約束:

    • Set<Characteristics> characteristics():

      Characteristics是Collector內的一個枚舉類,聲明瞭CONCURRENT、UNORDERED、IDENTITY_FINISH等三個屬性,用來約束Collector的屬性:

      • CONCURRENT:表示此收集器支持併發,意味着容許在多個線程中,累加器能夠調用結果容器
      • UNORDERED:表示收集器並不按照Stream中的元素輸入順序執行
      • IDENTITY_FINISH:表示finisher實現的是識別功能,可忽略。

      若是一個容器僅聲明CONCURRENT屬性,而不是UNORDERED屬性,那麼該容器僅僅支持無序的Stream在多線程中執行。

定義本身的Stream

  • collect

    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);              
    複製代碼
    • <1> <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner)

      Supplier supplier是一個工廠函數,用來生成一個新的容器;

      BiConsumer accumulator也是一個函數,用來把Stream中的元素添加到結果容器中;

      BiConsumer combiner仍是一個函數,用來把中間狀態的多個結果容器合併成爲一個(併發的時候會用到)

      Supplier<List<String>> supplier = ArrayList::new;
      BiConsumer<List<String>, String> accumulator = List::add;
      BiConsumer<List<String>, List<String>> combiner = List::addAll;
      
      //return [aaa1, aaa1],實現了Collectors.toCollection
      List<String> list1 = stringCollection.stream()
              .filter(x -> x.startsWith("a"))
              .collect(supplier, accumulator, combiner);
      複製代碼
    • <2> <R, A> R collect(Collector<? super T, A, R> collector)

      Collectors是Java已經提供好的一些工具方法:

      List<String> stringCollection = new ArrayList<>();
      stringCollection.add("ddd2");
      stringCollection.add("aaa1");
      stringCollection.add("bbb1");
      stringCollection.add("aaa1");
      複製代碼

      轉換成其餘集合:

      • toList

        //return [aaa1, aaa1]
        stringCollection.stream()
            .filter(x -> x.startsWith("a")).collect(Collectors.toList())
        複製代碼
      • toSet

        //return [aaa1]
        stringCollection.stream()
            .filter(x -> x.startsWith("a")).collect(Collectors.toSet())
        複製代碼
      • toCollection

        接口:

        public static <T, C extends Collection<T>> Collector<T, ?, C> toCollection(Supplier<C> collectionFactory)
        複製代碼

        實現:

        //return [aaa1, aaa1]
        List<String> list = stringCollection.stream()
            .filter(x -> x.startsWith("a"))
            .collect(Collectors.toCollection(ArrayList::new));
        複製代碼
      • toMap

        接口:

        public static <T, K, U>
        Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                              Function<? super T, ? extends U> valueMapper) 
        複製代碼

        實現:

        //return {aaa1=aaa1_xu}
        Function<String, String> xu = x -> x + "_xu";
        Map<String, String> map = stringCollection.stream()
            .filter(x -> x.startsWith("a"))
            .distinct()
            .collect(Collectors.toMap(Function.identity(), xu));
        複製代碼

      轉成值:

      • averagingDouble:求平均值,Stream的元素類型爲double
      • averagingInt:求平均值,Stream的元素類型爲int
      • averagingLong:求平均值,Stream的元素類型爲long
      • counting:Stream的元素個數
      • maxBy:在指定條件下的,Stream的最大元素
      • minBy:在指定條件下的,Stream的最小元素
      • reducing: reduce操做
      • summarizingDouble:統計Stream的數據(double)狀態,其中包括count,min,max,sum和平均。
      • summarizingInt:統計Stream的數據(int)狀態,其中包括count,min,max,sum和平均。
      • summarizingLong:統計Stream的數據(long)狀態,其中包括count,min,max,sum和平均。
      • summingDouble:求和,Stream的元素類型爲double
      • summingInt:求和,Stream的元素類型爲int
      • summingLong:求和,Stream的元素類型爲long

      數據分區:

      • partitioningBy

        接口:

        public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate)
        
        public static <T, D, A>
        Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
                                                           Collector<? super T, A, D> downstream)
        複製代碼

        實現:

        Predicate<String> startA = x -> x.startsWith("a");
        //return {false=[ddd2, bbb1], true=[aaa1, aaa1]}
        Map<Boolean, List<String>> map2 = stringCollection.stream()
                .collect(Collectors.partitioningBy(startA));
        
        //return {false={false=[ddd2], true=[bbb1]}, true={false=[], true=[aaa1, aaa1]}}
        Predicate<String> end1 = x -> x.endsWith("1");
        Map<Boolean, Map<Boolean, List<String>>> map3 = stringCollection.stream()
                .collect(Collectors.partitioningBy(startA, Collectors.partitioningBy(end1)));
        複製代碼

      數據分組:

      • groupingBy

        接口:

        public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)
        
        public static <T, K, A, D>
        Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
                                        Collector<? super T, A, D> downstream)
        
        public static <T, K, D, A, M extends Map<K, D>>
        Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,Supplier<M> mapFactory,
                                Collector<? super T, A, D> downstream)
        複製代碼

        實現:

        //rerurn {a=[aaa1, aaa1], b=[bbb1], d=[ddd2]}
        Function<String, String> stringStart = x -> String.valueOf(x.charAt(0));
        Map<String, List<String>> map4 = stringCollection.stream()
                .collect(Collectors.groupingBy(stringStart));
        
        //rerurn {ddd2=1, bbb1=1, aaa1=2}
        Map<String, Long> map5 = stringCollection.stream()
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
        
        //rerurn {d=1, a=2, b=1}
        Map<String, Long> map6 = stringCollection.stream()
                .collect(Collectors.groupingBy(stringStart, LinkedHashMap::new, Collectors.counting()));
        複製代碼
  • reduce

    reduce有三個接口:

    Optional<T> reduce(BinaryOperator<T> accumulator);
    
    <U> U reduce(U identity,
                 BiFunction<U, ? super T, U> accumulator,
                 BinaryOperator<U> combiner);
    
    T reduce(T identity, BinaryOperator<T> accumulator);
    複製代碼
    • <1> Optional<T> reduce(BinaryOperator<T> accumulator)

      BinaryOperator<String> binaryOperator = (x, y) -> x + y;
      //rerurn ddd2aaa1bbb1aaa1
      String reduceStr1 = stringCollection.stream().reduce(binaryOperator).orElse("");
      複製代碼
    • <2> T reduce(T identity, BinaryOperator<T> accumulator)

      //return start:ddd2aaa1bbb1aaa1
      String reduceStr2=stringCollection.stream().reduce("start:",binaryOperator);
      複製代碼
    • <3> <U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner)

      第一個參數返回實例u,傳遞你要返回的U類型對象的初始化實例u

      BiFunction accumulator,負責數據的累加

      BinaryOperator combiner,負責在並行狀況下最後合併每一個reduce線程的結果

      List<Person> personList = new ArrayList<>();
      personList.add(new Person(10, 20));
      personList.add(new Person(20, 30));
      personList.add(new Person(30, 50));
      
      BiFunction<Person, Person, Person> biFunction = (x, y) -> new Person(x.getAge() + y.getAge(), x.getRate() + y.getRate());
      BinaryOperator<Person> binaryOperator1 = (x, y) -> new Person(x.getAge() + y.getAge(), x.getRate() + y.getRate());
      Person total = personList.stream().reduce(new Person(0, 0), biFunction, binaryOperator1);
      System.out.println("total:"+total);
      複製代碼

    Java8-實踐

  • Map的雙重循環

    //對map的entry對象來作stream操做,使用兩次forEach
        Map<String, Long> map = new HashMap<>();
        crowdMap.entrySet().stream()
                .map(Map.Entry::getValue)
                .forEach(x -> x.entrySet().forEach(y -> {
                    if (map.containsKey(y.getKey()))
                        map.put(y.getKey(), map.get(y.getKey()) + y.getValue());
                    else map.put(y.getKey(), y.getValue());
                }));
    
        //對map的entry對象來作stream操做,使用flatMap將stream合併
        Map<String, Long> map = new HashMap<>();
        crowdMap.entrySet().stream()
                .map(Map.Entry::getValue)
                .flatMap(x -> x.entrySet().stream())
                .forEach(y -> {
                    if (map.containsKey(y.getKey()))
                        map.put(y.getKey(), map.get(y.getKey()) + y.getValue());
                    else map.put(y.getKey(), y.getValue());
                });
    
        //使用map自己的foreach語句            
        Map<String, Long> map = new HashMap<>();
        crowdMap.forEach((key, value) -> value.forEach((x, y) -> {
            if (map.containsKey(x))
                map.put(x, map.get(x) + y);
            map.put(x, y);
        }));
    複製代碼
  • List的屢次分組

    //使用groupingBy將ApproveRuleDetail對象分別按照item和detail分組,並計次
        Map<String, Map<String, Long>> detailMap = approveRuleDetailList.stream()
                .collect(Collectors
                        .groupingBy(ApproveRuleDetail::getItem, Collectors.
                                groupingBy(ApproveRuleDetail::getDetail, Collectors.counting())));
    複製代碼
  • List按照自定義條件分組

    //使用自定義的Function函數,將年齡按照每10歲分組
        Function<Integer, Integer> ageGroup = x -> x / 10;
        Map<Integer, List<StatisticsPipeline>> ageMap = statisticsPipelineList
                .stream()
                .collect(Collectors.groupingBy(y -> ageGroup.apply(y.getAge())));
    複製代碼
    //將年齡按不一樣方式分組
        Function<Integer, Integer> ageCredit = x -> {
            if (x <= 18)
                return 18;
            else if (x >= 40)
                return 40;
            else return x;
        };
    
        //將StatisticsPipeline轉化爲suggestion
        ToDoubleFunction<StatisticsPipeline> mapper = StatisticsPipeline::getSuggestion;
    
        //將人羣按照不一樣年齡分組,並計算每一個年齡段的suggestion的平均值
        Map<Integer, Double> ageCreditMap = statisticsPipelineList
                .stream()
                .collect(Collectors.groupingBy(y -> ageCredit.apply(y.getAge()), Collectors.averagingDouble(mapper)));
    複製代碼
  • 多個數據求集合

    //合併數據
        private BiFunction<Integer[], ApprovePipeline, Integer[]> accumulator = (x, y) -> new Integer[]{
                x[0] + y.getAuth(), x[1] + y.getAntiFraud(), x[2] + y.getCreditRule(), x[3] + y.getModelReject(), x[4] + y.getSuggestion()
        };
    
        //合併集合
        private BinaryOperator<Integer[]> combiner = (x, y) -> new Integer[]{x[0] + y[0], x[1] + y[1], x[2] + y[2], x[3] + y[3], x[4] + y[4]};
    
        //將ApprovePipeline對象的不一樣數據相加
        Integer[] detail = approvePipelineList.stream().reduce(new Integer[]{0, 0, 0, 0, 0}, accumulator, combiner);
    複製代碼
  • 多個數據求集合-多重合並

    private BiFunction<Integer[], ApprovePipeline, Integer[]> accumulator = (x, y) -> new Integer[]{
            x[0] += y.getAuth(), x[1] += y.getAntiFraud(), x[2] += y.getCreditRule(), x[3] += y.getModelReject(), x[4] += y.getSuggestion()
        };
        //合併數據
        BiFunction<Integer[], Map.Entry<String, List<ApprovePipeline>>, Integer[]> newAccumulator = (x, y) -> {
            List<ApprovePipeline> pipelineList = y.getValue();
            Integer[] data = pipelineList.stream().reduce(new Integer[]{0, 0, 0, 0, 0}, accumulator, combiner);
            return new Integer[]{
                    x[0] += data[0], x[1] += data[1], x[2] += data[2], x[3] += data[3], x[4] += data[4]
            };
        };
        //最終reduce
        Integer[] total = channelMap.entrySet().stream().reduce(new Integer[]{0, 0, 0, 0, 0}, newAccumulator, combiner);
    複製代碼
  • map最大多項和

    Long hourC3 = hourMap.entrySet().stream().mapToLong(Map.Entry::getValue).sorted().limit(3).sum();
    複製代碼

在這裏插入圖片描述
相關文章
相關標籤/搜索