Java8中創建Stream 流的四種方式以及 Stream 中間操作

Stream api

**Stream api 是java8 中提供的對集合處理的api , 對數據進行一系列的中間操作,元數據不會發生改變
                集合講的是數據, 流 講的是計算(用於操作數據源,集合,數組)所生成的元素序列。**
                
         Stream API位於 java.util.stream.* 包下。

1 Stream 自己不會存儲元素

                   2 Stream 不會改變源對象。相反,他們會返回一個持有結果的性Sstream 。
                  3 Stream 操作是延遲執行的。這以爲這他們會等到需要結果的時候才執行(延遲加載)。

一 創建裏Stream 流的四種方式

### 1 第一種 通過Collection得Stream()方法(串行流)或者 parallelStream()方法(並行流)創建Stream。

         List<String> list = Arrays.asList("1","2","3","4","0","222","33");
        Stream<String> stream = list.stream();
         Stream<String> stream1 = list.parallelStream();

### 2 通過Arrays中得靜態方法stream()獲取數組流

        IntStream stream = Arrays.stream(new int[]{1,2,3});

### 3 通過Stream類中得 of()靜態方法獲取流


       Stream<String> stream = Stream.of("a","b","c");

### 4 創建無限流(迭代、生成)

//迭代(需要傳入一個種子,也就是起始值,然後傳入一個一元操作)
     Stream<Integer> stream1 = Stream.iterate(2, (x) -> x * 2);

     //生成(無限產生對象)
     Stream<Double> stream2 = Stream.generate(() -> Math.random());
       

二 Stream 中間操作

多箇中間操作可以連接起來形成一個流水線,除非流水線終止操作,否則中間操作不會執行任何處理。
終止操作時一次性全部處理,稱爲“延遲加載”

1 篩選切片

1 過濾
List<String> list = Arrays.asList("1","2","3","4","0","222","33");
Stream<String> stream = list.stream().filter((x) -> {
            System.out.println(" api  中建操作。");
            return x.equals("3");
        });
        //終止操作:只有執行終止操作纔會執行全部。即:延遲加載
        stream.forEach(System.out::println);

結果

 api  中建操作。
 api  中建操作。
 api  中建操作。
3
 api  中建操作。
 api  中建操作。
 api  中建操作。
 api  中建操作。
2 limit() 截斷流,使其元素不超過給定數量。
List<String> list = Arrays.asList("1","2","3","4","0","222","33","3","3");
 Stream<String> stream = list.stream().filter((x) -> {
            System.out.println(" api  中建操作。");
            return x.equals("3");
        });
        //取兩個 , 可以配合其他得中間操作,並截斷流,取到相應的元素個數,這不會往下執行,可以提高效率
        stream.limit(2).forEach(System.out::println);

3 skip(n) 跳過元素

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

List<String> list = Arrays.asList("1","2","3","4","0","222","33","3","3");
        Stream<String> stream = list.stream().filter((x) -> {
            System.out.println(" api  中建操作。");
            return x.equals("3");
        });
        //skip(n),返回一個扔掉了前n個元素的流。若流中元素不足n個,則返回一個空,與limit(n)互補。
        stream.skip(3).limit(1).forEach(System.out::println);

4 篩選

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

List<String> list = Arrays.asList("1","2","3","4","0","222","33","3","3");
 Stream<String> stream = list.stream();
        stream.distinct().forEach(System.out::println);
1
2
3
4
0
222
33

5 映射

map - 接受lambda 將元素轉換爲其他形式或提取信息。

接受一個函數作爲參數,該函數會被應用到每個元素上,並將其映射成一個新元素



flatMap 接受一個函數作爲參數,將流中的每個值都轉成另一個流,然後把所有流連成一個流。

List<Stu> stuList = Arrays.asList(new Stu("a",1),new Stu("ab",3),new Stu("c",11),new Stu("f",12));
 
   Stream<Stu> stream = stuList.stream();
        //去除list中所有的年齡
        stream.map(Stu::getAge).forEach(System.out::println);
        //把所有年齡再返回一個集合
        List<Integer> collect = stream.map(Stu::getAge).collect(Collectors.toList());

        stream.flatMap(stu -> test1.filterCharacter(stu.getName())).forEach(System.out::println);

6 排序

sorted有兩種方法,一種是不傳任何參數,叫自然排序,還有一種需要傳Comparator 接口參數,叫做定製排序。

 //自然排序
        List<String> collect = list.stream().sorted().collect(Collectors.toList());
        
        List<String> collect2 = list.stream().sorted((o1, o2) -> {
            if(o1.length()>o2.length()){
                return 1;
            }else 
            if(o1.length()<o2.length()){
                return -1;
            }else {
                return 0;

            }
        }).collect(Collectors.toList());

三 Stream 終止操作

實體類

public class Person {
    String name ;
    String sex ;
    int age;
    Status statusEnum;

    public Person(String name, String sex, int age, Status statusEnum) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.statusEnum = statusEnum;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Status getStatusEnum() {
        return statusEnum;
    }

    public void setStatusEnum(Status statusEnum) {
        this.statusEnum = statusEnum;

}

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", statusEnum=" + statusEnum +
                '}';
    }
}

操作

 List<Person> persons = Arrays.asList(
                          new Person("張三", "男", 76, Status.FREE),
              new Person("李四", "女", 12, Status.BUSY),
               new Person("王五", "男", 35, Status.BUSY),
               new Person("趙六", "男", 3, Status.FREE),
               new Person("錢七", "男", 56, Status.BUSY),
               new Person("翠花", "女", 34, Status.VOCATION),
               new Person("翠花", "女", 34, Status.FREE),
               new Person("翠花", "女", 34, Status.VOCATION)
              );

1 查找與匹配

##### 1 allMatch —— 檢查是否匹配所有元素。

    public void test1(){
        boolean allMatch = persons.stream().allMatch((x) -> {
            return x.getStatusEnum().equals(Status.FREE);
        });

        System.out.println(allMatch);
    }
2 anyMatch —— 檢查是否至少匹配一個元素。
    public void test2(){
        boolean allMatch = persons.stream().anyMatch((x) -> {
            return x.getStatusEnum().equals(Status.FREE);
        });

        System.out.println(allMatch);
    }
3 noneMatch —— 檢查是否沒有匹配所有元素。
  檢查 所有的是否都是 FREE  ----- 結果是false
    public void test3(){
        boolean allMatch = persons.stream().noneMatch((x) -> {
            return x.getStatusEnum().equals(Status.FREE);
        });

        System.out.println(allMatch);
    }
4 findFirst —— 返回第一個元素。
 public void test4(){
      Optional<Person> first = persons.stream().findFirst();

      System.out.println(first.get());
  }

##### 5 findAny —— 返回當前流中任意元素。

public void test5(){
     Optional<Person> first = persons.stream().findAny();
     //first.orElse(new Person());  如果沒空 可以穿一個新的對象去代替它
     System.out.println(first.get());
 }

##### 6 count —— 返回流中元素總個數。

  public void test6(){
      long first = persons.stream().count();
      System.out.println(first);
  }

##### 7 max —— 返回流中最大值。

public void test7(){
     Optional<Person> person = persons.stream().max((x,y) ->  Integer.compare(x.age, y.age));
     System.out.println(person.get());
 }

##### 8 min —— 返回流中最小值。

public void test8(){
      Optional<Person> person = persons.stream().min((x,y) ->  Integer.compare(x.age, y.age));
      System.out.println(person.get());
  }

2 歸約 : 可以將流中元素反覆結合在一起,得到一個值

1 reduce(T identitty,BinaryOperator)首先,需要傳一個起始值,然後,傳入的是一個二元運算。
  public void test9(){
       List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
               // identitty 起始值 0  然後與集合中的值進行 相應的運算,再次賦值給 identity 然後 在進行運算。
                Integer sum = list.stream().reduce(0, (x, y) -> x + y);
       System.out.println(sum);
   }

##### 2 reduce(BinaryOperator)此方法相對於上面方法來說,沒有起始值,則有可能結果爲空,所以返回的值會被封裝到Optional中。

map和reduce的連接通常稱爲map-reduce模式,因Google用它來進行網絡搜索而出名。

用map 來提取 對象中某個屬性,然後再用reduce 進行歸約。
    public void test10() {
        Optional<Integer> reduce = persons.stream().map(Person::getAge).reduce(Integer::sum);
        System.out.println(reduce.get());
    }
3 收集 : 收集collect(將流轉換爲其他形式。接收一個Collector接口得實現,用於給其他Stream中元素做彙總的方法)
 
       Collector接口中方法得實現決定了如何對流執行收集操作(如收集到List,Set,Map)。
       但是Collectors實用類提供了很多靜態方法,可以方便地創建常見得收集器實例。
 
1 Collectors.toList() 將流轉換成List
 public void test11() {
     List<Person> collect = persons.stream().collect(Collectors.toList());
     collect.forEach(System.out::println);
 }

###### 2 將流轉換成HashSet

     public void test12() {
      //hashset會去重複
          Set<String> collect = persons.stream().map(Person::getName).collect(Collectors.toSet());
          collect.forEach(System.out::println);
      }

###### 3 將流轉換成其他集合

public void test13() {

      Set<Integer> collect = persons.stream().map(Person::getAge).collect(Collectors.toCollection(LinkedHashSet::new));
      collect.forEach(System.out::println);
  }

##### 4 Collectors.counting() 元素個數

 public void test14() {

      Long collect = persons.stream().map(Person::getAge).collect(Collectors.counting());
      System.out.println(collect);
  }

##### 5 將流轉換爲其他形式 , 接受一個conllectors接口的實現,用於給Stream中元素做彙總的方法

public void test14s() {
        // 1 對元素進行彙總方法
        DoubleSummaryStatistics collect = persons.stream().collect(Collectors.summarizingDouble(Person::getAge));
        IntSummaryStatistics collect2 = persons.stream().collect(Collectors.summarizingInt(Person::getAge));
        System.out.println(collect.getMax());
        System.out.println(collect.getAverage());
        System.out.println(collect.getCount());
        System.out.println(collect.getMin());
        System.out.println(collect.getSum());

###### 2 講元素轉換爲其他形式

       String collect1 = persons.stream().map(Person::getName).collect(Collectors.joining(",","頭","尾"));
        String collect3 = persons.stream().map(Person::getName).collect(Collectors.joining());
        System.out.println(collect1); //頭張三,李四,王五,趙六,錢七,翠花,翠花,翠花尾
        System.out.println(collect3); // 張三李四王五趙六錢七翠花翠花翠花
    }

    1. Collectors.averagingDouble()
    2  Collectors.averagingDouble()
    3 Collectors.averagingLong()

    平均數,這三個方法都可以求平均數,不同之處在於傳入得參數類型不同,返回值都爲Double
    public void test15() {

        Double s = persons.stream().collect(Collectors.averagingDouble(Person::getAge));
        System.out.println(s);
    }

##### 8 Collectors.maxBy() 求最大值

      public void test16() {

          Optional<Person> collect = persons.stream().collect(Collectors.maxBy((o1, o2) -> Integer.compare(o1.age, o2.age)));
          System.out.println(collect.get().age);
      }

##### 9 Collectors.minBy() 求最小值

 public void test17() {

     Optional<Person> collect = persons.stream().collect(Collectors.minBy((o1, o2) -> Integer.compare(o1.age, o2.age)));
     System.out.println(collect.get().age);
 }
10 Collectors.groupingBy()分組 ,返回一個map
按照 Status 分組
  public void test18() {

      Map<Status, List<Person>> collect = persons.stream().collect(Collectors.groupingBy(Person::getStatusEnum));
      collect.forEach((status, people) -> {
          System.out.println(" status === " + status);
          people.forEach(System.out::println);
      });
  }

###### 11 多級分組

  Collectors.groupingBy()還可以實現多級分組
 public void test19() {

     Map<Status, Map<String, List<Person>>> collect = persons.stream().collect(Collectors.groupingBy(Person::getStatusEnum,Collectors.groupingBy(Person::getSex)));
     Map<Status, Map<String, List<Person>>> collect2 = persons.stream().collect(Collectors.groupingBy(Person::getStatusEnum,Collectors.groupingBy(
             e->{
                 if (e.getAge()>10){
                     return "小孩";
                 }else {
                     return "大人";
                 }
             }
     )));
     System.out.println(collect);
     System.out.println(collect2);
 }

##### 12 分區

Collectors.partitioningBy() 分區,參數中傳一個函數,返回true,和false 分成兩個區
public void test20() {
    年齡大於39的分區  不滿足再的分區
      Map<Boolean, List<Person>> collect = persons.stream().collect(Collectors.groupingBy(e -> e.getAge() > 30));

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