1. 程式人生 > >Java8 學習筆記

Java8 學習筆記

文章目錄

1.Lambda表示式

  可以把Lambda表示式理解為簡潔地表示可傳遞的匿名函式的一種方式:它沒有名稱,但它有引數列表、函式主體、返回型別,可能還有一個可以丟擲的異常列表,如下所示簡單的Lamdda表示式:
在這裡插入圖片描述

2.函式式介面

     函式式介面定義且只定義了一個抽象方法,需要使用@FunctionalInterface,個標註用於表示該介面會設計成一個函式式介面
     函式式介面的抽象方法的簽名基本上就是Lambda表示式的簽名。我們將這種抽象方法叫作函式描述符

常用函式式介面

函式式介面 函式描述符 原始型別特化
Predicate T->boolean IntPredicate,LongPredicate, DoublePredicate
Consumer T->void IntConsumer,LongConsumer, DoubleConsumer
Function<T,R> T->R IntFunction,IntToDoubleFunction,IntToLongFunction,
LongFunction,LongToDoubleFunction,
LongToIntFunction,DoubleFunction,
ToIntFunction,ToDoubleFunction,ToLongFunction
Supplier ()->T BooleanSupplier,IntSupplier, LongSupplier,DoubleSupplier
UnaryOperator T->T IntUnaryOperator,LongUnaryOperator,
DoubleUnaryOperator
BinaryOperator (T,T)->T IntBinaryOperator,LongBinaryOperator,
DoubleBinaryOperator
BiPredicate<L,R> (L,R)->boolean
BiConsumer<T,U> (T,U)->void ObjIntConsumer,ObjLongConsumer,
ObjDoubleConsumer
BiFunction<T,U,R> (T,U)->R ToIntBiFunction<T,U>,ToLongBiFunction<T,U>,
ToDoubleBiFunction<T,U>

3.方法引用

先前:
   inventory.sort((Apple a1, Apple a2)-> a1.getWeight().compareTo(a2.getWeight()));
使用方法引用和 java.util.Comparator.comparing:
   inventory.sort(comparing(Apple::getWeight));  //使用“::”這個來呼叫方法,
   一般沒有對原始資料做其他特殊處理,可以用方法引用的更直觀簡單,如果沒辦法還是得用Lambda表示式。

4.使用流

4.1.流主要是對集合的操作處理

filter:謂詞篩選
foreach:輸出每一個元素
distinct:篩選掉相同元素
limit(n):截斷流,獲取指定的前n個數據
 skip(n):跳過集合前n個元素
 map:表示對映元素,集合中的一個元素對映到一個新的元素
 flatMap:扁平化集合,可以把兩個集合合併成一個集合
allMatch:流中是否有一個元素能匹配給定的謂詞
anyMatch:流中的元素是否都能匹配給定的謂詞
noneMatch:它可以確保流中沒有任何元素與給定的謂詞匹配
findFirst:將返回當前流中的任意元素
findAny:找到當前流中的第一個元素
reduce:規約資料(對每一個元素做累積值,可以求和,積,求最大值,最小值,可以給定初始值,也可以不給定初始值)
count:計算流中元素的個數
sorted:排序

如下具體的詳情描述:
在這裡插入圖片描述

 flatMap例子一:
  String[]  words = {"Goodbye", "World"}; //如下通過flatMap可以獲取這個陣列中包含的所有字元(不重複)
  List<String> uniqueCharacters =words.stream()
                      .map(w -> w.split(""))
                      .flatMap(Arrays::stream)
                      .distinct()
                      .collect(Collectors.toList());
                      
flatMap例子二:
  //如下可以讓兩個陣列的數自由的組合
   List<Integer> numbers1 = Arrays.asList(1, 2, 3);
   List<Integer> numbers2 = Arrays.asList(3, 4);
   List<int[]> pairs =numbers1.stream()
                       .flatMap(i -> numbers2.stream().map(j -> new int[]{i, j}))
                       .collect(toList());
                       
reduce帶初始值例子三:
int sum = numbers.stream().reduce(0, Integer::sum);

reduce不帶初始值例子三:
Optional<Integer> sum = numbers.stream().reduce((a, b) -> (a + b));

4.2.流轉換

1)對映到基本型別流

mapToInt:對映基本型別int的流, IntStream 還支援其他的方便方法,如max 、 min 、 average 等
mapToDouble:對映基本型別double的流
mapToLong:對映基本型別long的流

2)轉換回為物件流

boxed:相當於對基本型別的裝箱
mapToObject:這個也可以實現

3)數值範圍
range,rangeClosed
這兩個方法都是第一個引數接受起始值,第二個引數接受結束值。但
range 是不包含結束值的,而 rangeClosed 則包含結束值

例如:
IntStream.rangeClosed(1, 100)  //這個範圍是包含100的,結果的資料有50個
            .filter(n -> n % 2 == 0)  
IntStream.range(1, 100)
           .filter(n -> n % 2 == 0)  //這個範圍是不包含100的,結果的資料只有49個

4.3 建立流

1)使用Stream.of建立

Stream<String> stream = Stream.of("Java 8 ", "Lambdas ", "In ", "Action");

2)由陣列建立流

int[] numbers = {2, 3, 5, 7, 11, 13};
int sum = Arrays.stream(numbers).sum();

3)檔案流

 如下通過Files.lines建立流
long uniqueWords = 0;
try(Stream<String> lines =Files.lines(Paths.get("data.txt"), Charset.defaultCharset())){
     uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" ")))
                    .distinct()
                    .count();
}
catch(IOException e){
}

4)建立無限流
  Stream API提供了兩個靜態方法來從函式生成流: Stream.iterate 和Stream.generate 。 這兩個操作可以建立所謂的無限流:不像從固定集合建立的流那樣有固定大小的流。由 iterate
和 generate 產生的流會用給定的函式按需建立值,因此可以無窮無盡地計算下去!一般來說,應該使用 limit(n) 來對這種流加以限制,以避免列印無窮多個值。

i) iterate 方法要接受一個 UnaryOperator 作為引數,表示不停的迭代上一個數

 例子一:
  //Stream.iterate  如下是生成2,4,6,8...總共10個偶數,都是前一個數加2所得
		Stream.iterate(0, n -> n + 2)
              .limit(10)
             .forEach(System.out::println);
 例子二:
//Stream.iterate  可以用來生成斐波那契函式
   Stream.iterate(new int[]{0, 1},t -> new int[]{t[1],t[0] + t[1]})
         .limit(10)
         .map(t -> t[0])
         .forEach(System.out::println);
//這段程式碼將生成斐波納契數列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34…

ii) generate 方法也可讓你按需生成一個無限流。但 generate 不是依次對每個新生成的值應用函式的。它接受一個 Supplier 型別的Lambda提供新的值。

 例子一:
  Stream.generate(Math::random)
	    .limit(5)
        .forEach(System.out::println);//生成新的5個函式
例子二:
 //同樣生成斐波那契函式,不過這個存在有中間狀態,在並行條件下是不安全的,不建議這樣用
 IntSupplier fib = new IntSupplier(){
	 private int previous = 0;
	 private int current = 1;
	 public int getAsInt(){
 		 int oldPrevious = this.previous;
		 int nextValue = this.previous + this.current;
		 this.previous = this.current;
		 this.current = nextValue;
		return oldPrevious;
	  }
 };
IntStream.generate(fib).limit(10).forEach(System.out::println);

5.收集流

  收集流可以對流使用collect方法,然後使用Collector類提供的方法進行收集。

它們主要提供了三大功能:
a.   將流元素歸約和彙總為一個值
b.   元素分組
c.   元素分割槽
方法 說明
Collector.toList() 將流轉換為一個List集合
Collector.toSet 將流轉換為一個Set集合,不包含重複元素
Collector.toSet 將流收集起來成為集合
Collectors.counting() 可以返回流中有多少個元素
Collectors.maxBy(Comparator) 可以返回流裡最大的元素(某個條件)
Collectors.minBy(Comparator) 可以返回流裡最小的元素(某個條件)
Collectors.summingInt(Function) 對於流中的元素求和,返回int,同樣summingDouble則是返回double型別
Collectors.averagingDouble(Function) 對流中的元素求平均值返回double型別,同樣有averagingInt,averagingLong
Collectors.joining() 對CharSequence的元素流進行組合,可以使用帶引數做分割,以及前後新增元素
Collectors.reducing (U identity,Function<? super T, ? extends U> mapper,BinaryOperator op) 上面所有的都是這個reducing的特殊情況,都可以通過這個方法實現,這個有三個過載方法。
Collectors.groupingBy(Function) 對於流通過某一個元素進行分組,這個也支援巢狀分組,返回Map集合,第二個引數可以對生成的集合進行求和,數量計算,最大,最小等
Collectors.collectingAndThen 把結果集轉換為另外一個結果,一般可以對包裝的Optional進行get提取元素
Collectors.partitioningBy(Predicate) 對流進行分割槽,和GroupBy相似,不過只分為true和false兩組;他和可以和groupingBy巢狀使用

6.流中插入動作peek

  peek 的設計初衷就是在流的每個元素恢復執行之前,插入執行一個動作。但是它不像 forEach 那樣恢復整個流的執行,而是在一個元素上完成操作之後,它只會將操作順承到流水線中的下一個操作。

7.新的日期API

這個可以參考 https://www.cnblogs.com/comeboo/p/5378922.html