1. 程式人生 > >JDK8 Stream API

JDK8 Stream API

package com.hundsun.java.se.java8;

import org.apache.ibatis.reflection.SystemMetaObject;
import org.junit.Test;

import java.sql.SQLOutput;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description: Stream API
 * @author:zhangys
 * @date:Created in 21:22 2018/12/30
 * @Modified By:
 */
public class Demo3 {
    /**
     * stream 自己不會儲存元素
     * stream不會改變原物件,相反,他們會返回一個持有結果的新stream
     * stream操作是延遲的,這意味著他們會等到需要結果的時候才執行
     */

    /**
     * 一、stream的三個操作步驟
     * 1、建立stream
     * 2、中間操作
     * 3、終止操作(終端操作)
     */

    //建立stream
    @Test
    public void test1(){
        //1 可以 通過collection 系列集合提供的stream()或者parallelstream()
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();

        //2 通過Arrays中的靜態方法stream()獲取陣列流
        Employee[] emp = new Employee[10];
        Stream<Employee> stream1 = Arrays.stream(emp);

        //3 通過stream 類中的靜態方法of()
        Stream<String> stream2 = Stream.of("aa","bbb","cc");

        //4 建立無限流
        //迭代
        Stream<Integer> stream3 = Stream.iterate(0,(x) -> x + 2);
        //只顯示10個
        stream3.limit(10).forEach(System.out::println);

        System.out.println("-------------------------------------------");
        //生成
        Stream.generate(() -> Math.random())
        .limit(5)
        .forEach(System.out::println);
    }


    /**
     * 中間操作
     * filter -- 接收lambda,從流中排除某些元素
     * limit--截斷流,使其元素不超過給定元素
     * skip(n) --跳過元素,返回一個扔掉了前n個元素的流。若流中元素不足n個,則返回一個空流,與limit(n)互補
     * distinct--篩選,通過流所生產元素的hashcode()和equals()去除重複元素
     *
     *
     *  對映
     *  map--接收lambda ,將引數轉換成其他形式或提取資訊。接收一個函式作為引數,該函式會被應用到每個元素上,並將其形成一個新的元素
     *
     *  flatMap --接收一個函式作為引數,將流中的每一個值都轉換成另一個流,然後把所有流連線成一個流
     */

    List<Employee> employees = Arrays.asList(
            new Employee("zhangsan",19,9999.99,Employee.Status.BUSY),
            new Employee("lisi",38,5555.55,Employee.Status.FREE),
            new Employee("wangwu",50,6666.66, Employee.Status.VOCATION),
            new Employee("zhaoliu",16,3333.33,Employee.Status.FREE),
            new Employee("tianqi",18,7777.77,Employee.Status.VOCATION)
    );

    @Test
    public void test2(){
        Stream<Employee> s = employees.stream()
                .filter((e) -> {
                    System.out.println("中間操作");
                    return e.getAge() > 35;
                        }
                );
        //終止操作
        //多箇中間操作可以連線起來形成一個流水線,除非流水線上觸發終止操作,否則中間操作不會執行任何的處理
        //而在終止操作時一次性全部處理,稱為“惰性求值”
        s.forEach(System.out::println);
    }

    /**
     * limit
     */
    @Test
    public void test3(){
        employees.stream().filter((e) -> e.getSalary() > 5000)
                .limit(2)
                .forEach(System.out::println);
    }

    /**
     * skip
     */
    @Test
    public void test4(){
        employees.stream().filter((e) -> e.getSalary() > 5000)
                  .skip(2)
                  .forEach(System.out::println);
    }

    /**
     * distinct
     */
    @Test
    public void test5(){
        employees.stream().filter((e) -> e.getSalary() > 5000)
                .skip(2)
                //去重必須重寫employmee的hashcode和equals方法 才能去重生效
                .distinct()
                .forEach(System.out::println);
    }


    /**
     * 對映
     */
    @Test
    public void test6(){
        List<String> list = Arrays.asList("aaa","bb","cc","sss");

        list.stream().map((str) -> str.toUpperCase())
                .forEach(System.out::println);
        System.out.println("-------------------------");
        employees.stream()
                .map(Employee::getName)
                .forEach(System.out::println);

        System.out.println("--------------------------");

        Stream<Stream<Character>> stream = list.stream().map(Demo3::filterCharacter);
        stream.forEach((s) ->{
            s.forEach(System.out::println);
        });

        System.out.println("-------------------------");

        Stream<Character> stream1 = list.stream().flatMap(Demo3::filterCharacter);
        stream1.forEach(System.out::println);
    }

    public static Stream<Character> filterCharacter(String str){
        List<Character> list = new ArrayList<>();
        for (Character e : str.toCharArray()){
            list.add(e);
        }
        return list.stream();
    }

    /**
     * stream 排序
     *  sorted() --自然排序 (comparable)
     *  sorted(Comparator com) --定製排序(comparator)
     */
    @Test
    public void test7(){
        List<String> list = Arrays.asList("aaaa","您好","sss","哈嘍","hello");
        list.stream().sorted().forEach(System.out::println);


        System.out.println("---------------");


        employees.stream().sorted((e1,e2) -> {
           if (e1.getAge().equals(e2.getAge())){
               return e1.getName().compareTo(e2.getName());
           } else {
               return e1.getAge().compareTo(e2.getAge());
           }
        }).forEach(System.out::println);
    }


    /**
     * 終止操作
     *  1、stream 查詢和匹配
     *     allMatch--檢查是否匹配所有元素
     *     anyMatch--檢查是否至少匹配一個元素
     *     noneMatch--檢查是否沒有匹配的元素
     *     findFirst--返回第一個元素
     *     findAny--返回當前流中的任意元素
     *     count--返回流中元素的總個數
     *     max--返回流中的最大值
     *     min--返回流中最小值
     *
     *  2、歸約
     *  reduce(T identity,BinaryOperator) / reduce(BinaryOperator) --可以將流中元素反覆結合起來,得到一個值
     *
     */

    @Test
    public void test8(){
        boolean b1 = employees.stream()
                .allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b1);

        System.out.println("-------------------");
        boolean b2 = employees.stream()
                .anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b2);
        System.out.println("---------------------");

        boolean b3 = employees.stream()
                .noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));

        Optional<Employee> emp1 = employees.stream()
                .sorted((e1,e2) -> Double.compare(e1.getSalary(),e2.getSalary()))
                .findFirst();
        System.out.println("emp1:" + emp1.get());

        System.out.println("--------------------");

        Optional<Employee> emp2 = employees.stream()
                .filter((e) -> e.getStatus().equals(Employee.Status.FREE))
                .findAny();

        System.out.println(emp2);
        System.out.println("-----------------------");
        Optional<Employee> emp3 = employees.parallelStream()
                .filter((e) -> e.getStatus().equals(Employee.Status.FREE))
                .findAny();

        System.out.println(emp3);

        System.out.println("---------------");

        Long count = employees.stream().count();
        System.out.println("-----------------" + count);

        Optional<Employee> op = employees.stream().max((e1,e2) -> Double.compare(e1.getSalary(),e2.getSalary()));
        System.out.println(op);
        System.out.println("-------------------");
        Optional<Double> op2 = employees.stream().map(Employee::getSalary).min(Double::compareTo);
        System.out.println(op2.get());
    }


    /**
     * 歸約
     */
    /**
     * 蒐集
     */

    @Test
    public void test9(){
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
        Integer sum = list.stream().reduce(0,(x,y) -> x + y);
        System.out.println(sum + "-------------------");

        //OPtional 避免為null
        Optional<Double> op = employees.stream().map(Employee::getSalary).reduce(Double::sum);
        System.out.println(op.get() + " -----------------");

        List<String> list1 = employees.stream().map(Employee::getName).collect(Collectors.toList());
        list.forEach(System.out::println);

        List<person> personList = Arrays.asList(new person(
                "111","111","111"),
                new person("111","222","222"),
                new person("111","333","333"),
                new person("111","444","444")
                                               );
        personList.forEach((e) -> e.setAge(e.getAge() + "age"));
        System.out.println(personList);


        HashSet<String> hs = employees.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
        hs.forEach(System.out::println);
    }

    @Test
    public void test10(){
        //總數
        Long count = employees.stream().collect(Collectors.counting());
        System.out.println(count);

        //平均數
        System.out.println("----------------");
        double avg = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(avg);

        //總和
        Double sum = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(sum);

        System.out.println("---------------------");

        //最大值
        Optional<Employee> max = employees.stream().collect(Collectors.maxBy((e1,e2) -> Double.compare(e1.getSalary(),e2.getSalary())));
        System.out.println(max);

        System.out.println("----------------");

        //最小值
        Optional<Double> min = employees.stream()
                .map(Employee::getSalary)
                .collect(Collectors.minBy((Double::compare)));
        System.out.println(min);

        //分組

        Map<Employee.Status,List<Employee>> map = employees.stream().collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println(map);

        //多級分組
        Map<Employee.Status,Map<String,List<Employee>>> mapgroup = employees.stream().collect(Collectors.groupingBy(Employee::getStatus,Collectors.groupingBy((e) -> {
            if (((Employee)e).getAge() <= 35){
                return "青年";
            } else if (((Employee)e).getAge() <=50){
                return "中年";
            } else {
                return "老年";
            }
        })));

        System.out.println(map);

        //分割槽
        Map<Boolean,List<Employee>> map2 = employees.stream()
                .collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000));
        System.out.println(map2);

        //組函式
        DoubleSummaryStatistics dss = employees.stream().collect(Collectors.summarizingDouble(Employee::getSalary));

        System.out.println(dss.getAverage());
        System.out.println(dss.getCount());
        System.out.println(dss.getMax());


        String str = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.joining(","));
    }

    class person{
        private String name;
        private String age;
        private String status;

        public person(String name, String age, String status) {
            this.name = name;
            this.age = age;
            this.status = status;
        }

        public String getName() {
            return name;
        }

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

        public String getAge() {
            return age;
        }

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

        public String getStatus() {
            return status;
        }

        public void setStatus(String status) {
            this.status = status;
        }

        @Override
        public String toString() {
            return "person{" +
                    "name='" + name + '\'' +
                    ", age='" + age + '\'' +
                    ", status='" + status + '\'' +
                    '}';
        }
    }

}