1. 程式人生 > >java8_02_stream(二)終止操作

java8_02_stream(二)終止操作

三、終止操作

3.1 常見的八種操作
  • allMatch——檢查是否匹配所有元素
  • anyMatch——檢查是否至少匹配一個元素
  • noneMatch——檢查是否沒有匹配的元素
  • findFirst——返回第一個元素
  • findAny——返回當前流中的任意元素
  • count——返回流中元素的總個數
  • max——返回流中最大值
  • min——返回流中最小值

測試用例

public class Student {
    private String name;
    private Integer age;
    private Integer score;
    private Status status;

    public
Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getScore() { return score; } public
void setScore(Integer score) { this.score = score; } public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } public Student() { } public Student(String name, Integer age, Integer score) { this
.name = name; this.age = age; this.score = score; } public Student(String name, Integer age, Integer score, Status status) { this.name = name; this.age = age; this.score = score; this.status = status; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; if (name != null ? !name.equals(student.name) : student.name != null) return false; if (age != null ? !age.equals(student.age) : student.age != null) return false; return score != null ? score.equals(student.score) : student.score == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (age != null ? age.hashCode() : 0); result = 31 * result + (score != null ? score.hashCode() : 0); return result; } public enum Status{ FREE, BUSY, HAPPY } }

程式碼示例

public class StreamDemo3 {
    /*
     測試資料集合
    */
    List<Student> students = Arrays.asList(
            new Student("張三",18,88, Student.Status.BUSY),
            new Student("李四",18,80, Student.Status.BUSY),
            new Student("王五",19,60, Student.Status.FREE),
            new Student("王五",19,60, Student.Status.BUSY),
            new Student("王五",19,60, Student.Status.HAPPY),
            new Student("趙六",17,100, Student.Status.HAPPY)
    );

    @Test
    public void test(){
        boolean b = students.stream()
                .allMatch(s -> s.getAge() > 17);
        System.out.println(b);
    }

    @Test
    public void test2(){
           boolean b = students.stream()
                    .anyMatch(s->s.getAge()>17);
        System.out.println(b);
    }

    @Test
    public void test3(){
        boolean b = students.stream()
                .noneMatch(s->s.getAge()>100);
        System.out.println(b);
    }

    @Test
    public void test4(){
        Optional<Student> studentOptional = students.stream()
                .filter(s->s.getStatus().equals(Student.Status.BUSY))
                .findFirst();

        if (studentOptional.isPresent()){ // 判斷是否為null,避免空指標異常
            System.out.println(studentOptional.get()); //獲得結果
        }
    }

    @Test
    public void test5(){
        Optional<Student> studentOptional = students.stream()
                .filter(s->s.getStatus().equals(Student.Status.BUSY))
                .findAny(); // 滿足條件的任意一個
        if (studentOptional.isPresent()){
            System.out.println(studentOptional.get());
        }

        Optional<Student> studentOptional2 = students.parallelStream()
                .filter(s->s.getStatus().equals(Student.Status.BUSY))
                .findAny();
        if (studentOptional2.isPresent()){
            System.out.println(studentOptional2.get());
        }
    }

    @Test
    public void test6(){
       Long count = students.stream()
                .filter(s->s.getStatus().equals(Student.Status.BUSY))
                .count();
        System.out.println(count);
    }

    @Test
    public void test7(){
       Optional<Student> maxScoreStudent = students.stream()
                .filter(s->s.getStatus().equals(Student.Status.BUSY))
                .max(Comparator.comparingInt(Student::getScore)); //等同於 .max((s1,s2)->Integer.compare(s1.getScore(),s2.getScore()));
        System.out.println("busy狀態,分數最多:" +maxScoreStudent.get());
    }

    @Test
    public void test8(){
       Optional<Student> studentOptional = students.stream()
                .min(Comparator.comparingInt(Student::getAge)); //等同於 .min((s1,s2)-> Integer.compare(s1.getAge(),s2.getAge()));
        if (studentOptional.isPresent())
            System.out.println(studentOptional.get());
    }
}
3.2 歸約

reduce(T identity, BinaryOperator) / reduce(BinaryOperator):將流中的元素反覆結合起來,得到一個值

@Test
    public void test9(){
        List<Integer> integerList = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        //求和操作
        Integer sum = integerList.stream()
                            .reduce(0,Integer::sum); //reduce(初始因子,計算演算法)
        System.out.println(sum);

        //學生分數總和
        Optional<Integer> scoreSumOptional = students.stream()
                .map(Student::getScore)
                .reduce(Integer::sum); //沒有初始因子,所以返回的Optional<T> 集合類,可以避免空指標異常
        if (scoreSumOptional.isPresent())
            System.out.println(scoreSumOptional.get());
    }

    @Test
    public void test10(){
        //需求:名字中,“五”字出現的次數
        Optional<Integer> fiveOp = students.stream()
                .map(Student::getName)
                .flatMap(str ->{ //str->List<Character>-> Stream<Character>
                    List<Character> characters = new ArrayList<>();
                    for (Character ch : str.toCharArray()){
                        characters.add(ch);
                    }
                    return characters.stream();
                })
                .map(ch -> { // ‘五’出現一次,返回 1 ,
                            if (ch.equals('五') || ch == '五') { //注意 char使用單引號。換為雙引號後容易出錯
                                return 1;
                            } else return 0;
                        }
                ).reduce(Integer::sum); // 求和

        System.out.println(fiveOp.get());
    }
3.3 collect() 操作

collect():將流轉換成其他形式。接受一個Collector介面的實現,用於給Stream中元素做彙總的方法

 @Test
    public void testCollect(){
        List<String> nameList = students.stream()
                    .map(Student::getName)
                    .collect(Collectors.toList());
        nameList.forEach(System.out::println);
        System.out.println("---------------------------");
        Set<String> nameSet = students.stream()
                    .map(Student::getName)
                    .collect(Collectors.toSet());
        nameSet.forEach(System.out::println);
        System.out.println("---------------------------");
        HashSet<String> nameHashSet = students.stream()
                        .map(Student::getName)
                        .collect(Collectors.toCollection(HashSet::new)); //沒有toHashSet,只能 toCollection(HashSet::new)
        nameHashSet.forEach(System.out::println);
        System.out.println("---------------------------");
        LinkedList<String> nameLinked = students.stream()
                                            .map(Student::getName)
                                            .collect(Collectors.toCollection(LinkedList::new));
        nameLinked.forEach(System.out::println);
    }

    @Test
    public void test11(){
        Optional<Integer> integerMaxOptional =  students.stream().map(Student::getScore).max(Integer::compareTo);
        System.out.println(integerMaxOptional.get());

        Optional<Student> minOp = students.stream()
                                    .collect(Collectors.minBy((s1,s2)-> Integer.compare(s1.getAge(),s2.getAge())));
        System.out.println("年齡最小的物件:"+ minOp.get());
        Optional<Student> minOp2 = students.parallelStream()
                                    .min(Comparator.comparingInt(Student::getAge));
        System.out.println("年齡最小的物件:"+ minOp2.get());

        IntSummaryStatistics iss = students.stream().collect(Collectors.summarizingInt(Student::getAge));
        System.out.println(iss.getAverage()); //平均值
        System.out.println(iss.getCount()); //個數
        System.out.println(iss.getMax()); // 最大值
        System.out.println(iss.getMin()); // 最小值
        System.out.println(iss.getSum()); // 和
    }

分組操作

@Test
    public void test12(){
      //普通分組
       Map<Student.Status,List<Student>> groupByStatus = students.stream()
                .collect(Collectors.groupingBy(Student::getStatus));
        System.out.println(groupByStatus);

        //多級分組
      Map<Student.Status,Map<Integer,List<Student>>> manyGroup = students.stream()
                .collect(Collectors.groupingBy(Student::getStatus,Collectors.groupingBy(Student::getAge)));
      System.out.println(manyGroup);
      Map<Student.Status,Map<String,List<Student>>> manyGroup2 = students.stream()
                .collect(Collectors.groupingBy(Student::getStatus,Collectors.groupingBy(s ->{
                    if (s.getScore() < 60 ) return "未及格";
                    else if (s.getScore() > 80) return "優秀";
                    else return "普通";
                })));
        System.out.println(manyGroup2);
    }

分割槽操作:true:xxx,flase:xxx

@Test
    public void test13(){
        //分割槽,分成滿足條件的部分,和未滿足條件的部分
          Map<Boolean,List<Student>> partStudent = students.stream()
                   .collect(Collectors.partitioningBy(s-> s.getScore() > 75));
        System.out.println(partStudent);

        //多級分割槽  1->2->4 ...
         Map<Boolean,Map<Boolean,List<Student>>> fourPart = students.stream()
                .collect(Collectors.partitioningBy(s-> s.getScore() > 75,Collectors.partitioningBy( s2 -> s2.getAge() == 17 )));
        System.out.println(fourPart);
    }

連線操作

@Test
    public void test14(){
       String joinStr = students.stream()
                .map(Student::getName)
                .collect(Collectors.joining(","));
        System.out.println(joinStr);

        String joinStr2 = students.stream()
                .map(Student::getName)
                .collect(Collectors.joining(",","+","-"));
        System.out.println(joinStr2);
    }

總結
Stream使用總結
- 一個數據源(如集合) 如 執行一個查詢,獲得資料集合;
- 一箇中間操作鏈,形成一條流的流水線;
- 一個終端操作,執行流水線,並能生成結果。(eg:count()、collect(toList()) )

常見中間操作

操作 返回型別 操作引數 函式描述符
filter Stream Predicate T-> boolean
map Stream Function T -> R
limit Stream
sorted Stream Comparator (T,T) ->int
distinct Stream

常見終端操作

操作 型別 目的
forEach 終端 消費流中的每個元素並對其應用Lambda。返回void
count 終端 返回流中元素的個數。返回long
collect 終端 把流歸約成一個集合,比如List、Map甚至是Integer。