Java8新特性(二)-強大的Stream API

一,Stream說明

     Stream 是 Java8 中處理集合的關鍵抽象概念,它可以指定你希望對 集合進行的操作,可以執行非常複雜的查找、過濾和映射數據等操作。 使用Stream API 對集合數據進行操作,就類似於使用 SQL 執行的數 據庫查詢。也可以使用 Stream API 來並行執行操作。簡而言之, Stream API 提供了一種高效且易於使用的處理數據的方式。

 

1,流(Stream) 到底是什麼呢?

是數據渠道,用於操作數據源(集合、數組等)所生成的元素序列。 ,“集合講的是數據,流講的是計算! ” 

注意:

①Stream 自己不會存儲元素。

②Stream 不會改變源對象。相反,他們會返回一個持有結果的新Stream。

③Stream 操作是延遲執行的。這意味着他們會等到需要結果的時候才執行。

 

二,Stream的操作

 

1,Stream操作的三個步驟:

(1)創建 Stream :一個數據源(如: 集合、數組), 獲取一個流 

(2)中間操作 :一箇中間操作鏈,對數據源的數據進行處理 

(3)終止操作(終端操作) :一個終止操作,執行中間操作鏈,併產生結果

如圖:

 

2,創建Stream的幾種方式

(1)Java8 中的 Collection 接口被擴展,提供了 兩個獲取流的方法: 

 default Stream<E> stream() : 返回一個順序流

 default Stream<E> parallelStream() : 返回一個並行流

 

(2)Java8 中的 Arrays 的靜態方法 stream() 可 以獲取數組流: 

 static <T> Stream<T> stream(T[] array): 返回一個流

重載形式,能夠處理對應基本類型的數組:

 public static IntStream stream(int[] array)

 public static LongStream stream(long[] array)

 public static DoubleStream stream(double[] array)

 

(3)可以使用靜態方法 Stream.of(), 通過顯示值 創建一個流。它可以接收任意數量的參數。 

 public static<T> Stream<T> of(T... values) : 返回一個流

 

(4)可以使用靜態方法 Stream.iterate() 和 Stream.generate(), 創建無限流。 

 迭代

public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) 

 生成

public static<T> Stream<T> generate(Supplier<T> s)

 

代碼示例:

@Test
 public void test1(){
  //1. Collection 提供了兩個方法 stream() 與 parallelStream()
  List<String> list = new ArrayList<>();
  Stream<String> stream = list.stream(); //獲取一個順序流
  Stream<String> parallelStream = list.parallelStream(); //獲取一個並行流
  
  //2. 通過 Arrays 中的 stream() 獲取一個數組流
  Integer[] nums = new Integer[10];
  Stream<Integer> stream1 = Arrays.stream(nums);
  
  //3. 通過 Stream 類中靜態方法 of()
  Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6);
  
  //4. 創建無限流
  //迭代
  Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2).limit(10);
  stream3.forEach(System.out::println);
  
  //生成
  Stream<Double> stream4 = Stream.generate(Math::random).limit(2);
  stream4.forEach(System.out::println);
 }

3,Stream的中間操作

多箇中間操作可以連接起來形成一個流水線,除非流水 線上觸發終止操作,否則中間操作不會執行任何的處理! 而在終止操作時一次性全部處理,稱爲“惰性求值” 。

(1)篩選與切片

filter——接收 Lambda , 從流中排除某些元素。

limit——截斷流,使其元素不超過給定數量。 

skip(n) —— 跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個,則返回一個空流。與 limit(n) 互補

distinct——篩選,通過流所生成元素的 hashCode() 和 equals() 去除重複元素

 

代碼示例:

@Test
 public void test2(){
  //所有的中間操作不會做任何的處理
  Stream<Employee> stream = emps.stream()
   .filter((e) -> {
    System.out.println("測試中間操作");
    return e.getAge() <= 35;
   });
  
  //只有當做終止操作時,所有的中間操作會一次性的全部執行,稱爲“惰性求值”
  stream.forEach(System.out::println);
 }
 
 //外部迭代
 @Test
 public void test3(){
  Iterator<Employee> it = emps.iterator();
  
  while(it.hasNext()){
   System.out.println(it.next());
  }
 }
 
 @Test
 public void test4(){
  emps.stream()
   .filter((e) -> {
    System.out.println("短路!"); // && ||
    return e.getSalary() >= 5000;
   }).limit(3)
   .forEach(System.out::println);
 }
 
 @Test
 public void test5(){
  emps.parallelStream()
   .filter((e) -> e.getSalary() >= 5000)
   .skip(2)
   .forEach(System.out::println);
 }
 
 @Test
 public void test6(){
  emps.stream()
   .distinct()
   .forEach(System.out::println);
 }

(2)映射

代碼示例:

@Test
 public void test1(){
  Stream<String> str = emps.stream()
   .map((e) -> e.getName());
  
  System.out.println("-------------------------------------------");
  
  List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
  
  Stream<String> stream = strList.stream()
      .map(String::toUpperCase);
  
  stream.forEach(System.out::println);
  
  Stream<Stream<Character>> stream2 = strList.stream()
      .map(TestStreamAPI1::filterCharacter);
  
  stream2.forEach((sm) -> {
   sm.forEach(System.out::println);
  });
  
  System.out.println("---------------------------------------------");
  
  Stream<Character> stream3 = strList.stream()
      .flatMap(TestStreamAPI1::filterCharacter);
  
  stream3.forEach(System.out::println);
 }
 public static Stream<Character> filterCharacter(String str){
  List<Character> list = new ArrayList<>();
  
  for (Character ch : str.toCharArray()) {
   list.add(ch);
  }
  
  return list.stream();
 }

(3)排序

代碼示例:

@Test
 public void test2(){
  emps.stream()
   .map(Employee::getName)
   .sorted()
   .forEach(System.out::println);
  
  System.out.println("------------------------------------");
  
  emps.stream()
   .sorted((x, y) -> {
    if(x.getAge() == y.getAge()){
     return x.getName().compareTo(y.getName());
    }else{
     return Integer.compare(x.getAge(), y.getAge());
    }
   }).forEach(System.out::println);
 }

4,Stream的終止操作

(1)查找與匹配

代碼示例:

List<Employee> emps = Arrays.asList(
   new Employee(102, "李四", 59, 6666.66, Status.BUSY),
   new Employee(101, "張三", 18, 9999.99, Status.FREE),
   new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
   new Employee(104, "趙六", 8, 7777.77, Status.BUSY),
   new Employee(104, "趙六", 8, 7777.77, Status.FREE),
   new Employee(104, "趙六", 8, 7777.77, Status.FREE),
   new Employee(105, "田七", 38, 5555.55, Status.BUSY)
 );
 
 @Test
 public void test1(){
   boolean bl = emps.stream()
    .allMatch((e) -> e.getStatus().equals(Status.BUSY));
   
   System.out.println(bl);
   
   boolean bl1 = emps.stream()
    .anyMatch((e) -> e.getStatus().equals(Status.BUSY));
   
   System.out.println(bl1);
   
   boolean bl2 = emps.stream()
    .noneMatch((e) -> e.getStatus().equals(Status.BUSY));
   
   System.out.println(bl2);
 }
 
 @Test
 public void test2(){
  Optional<Employee> op = emps.stream()
   .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
   .findFirst();
  
  System.out.println(op.get());
  
  System.out.println("--------------------------------");
  
  Optional<Employee> op2 = emps.parallelStream()
   .filter((e) -> e.getStatus().equals(Status.FREE))
   .findAny();
  
  System.out.println(op2.get());
 }
 
 @Test
 public void test3(){
  long count = emps.stream()
       .filter((e) -> e.getStatus().equals(Status.FREE))
       .count();
  
  System.out.println(count);
  
  Optional<Double> op = emps.stream()
   .map(Employee::getSalary)
   .max(Double::compare);
  
  System.out.println(op.get());
  
  Optional<Employee> op2 = emps.stream()
   .min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
  
  System.out.println(op2.get());
 }
 
 //注意:流進行了終止操作後,不能再次使用
 @Test
 public void test4(){
  Stream<Employee> stream = emps.stream()
   .filter((e) -> e.getStatus().equals(Status.FREE));
  
  long count = stream.count();
  
  stream.map(Employee::getSalary)
   .max(Double::compare);
 }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章