java8新特性 stream中間操作和終端操作示例說明java8新特性(查找、 排序、 過濾 、計算、 去重 、分組 等操作)

java8 的forEach、filter、map、distinct、sorted、peek、limit、skip、count、anyMatch、allMatch、noneMatch、toArray操作、min、max、findFirst、findAny、reduce、collect操作 示例說明

 

package com.zpy.demo.java8;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;


/**
 * @Author: Administrator
 * @Description:
 * @Date:Create:in 2019/10/16 15:53
 */
public class LambdaDemo {

    public static void main(String[] args){
        List<Person> p1=getPersonList();
        /**
         * 遍歷
         void forEach(Consumer<? super T> action);
         void forEachOrdered(Consumer<? super T> action)
         */
        List<String> strsss = Arrays.asList("a", "b", "c");
        strsss.stream().forEachOrdered(System.out::print);//abc
        strsss.stream().forEach(System.out::print);//abc
        strsss.parallelStream().forEachOrdered(System.out::print);//abc
        strsss.parallelStream().forEach(System.out::print);//bca
        //先看第一段輸出和第二段輸出,使用的是stream的流,這個是一個串行流,也就是程序是串行執行的,所有看到遍歷的結果都是按照集合的元素放入的順序;
        //看第三段和第四段輸出,使用的parallelStream的流,這個流表示一個並行流,也就是在程序內部迭代的時候,會幫你免費的並行處理
        //第三段代碼的forEachOrdered表示嚴格按照順序取數據,forEach在並行中,隨機排列了;這個也可以看出來,在並行的程序中,如果對處理之後的數據,沒有順序的要求,使用forEach的效率,肯定是要更好的

        /**
         * 按條件過濾
         *  Stream<T> filter(Predicate<? super T> predicate);
         *  這個方法,傳入一個Predicate的函數接口,這個接口傳入一個泛型參數T,做完操作之後,返回一個boolean值;filter方法的作用,
         *  是對這個boolean做判斷,返回true判斷之後的對象,下面一個案例,可以看到怎麼使用
         */
        //Predicate 接口定義 可以用作判斷使用
        Predicate<Person> predicate = x -> x.getAge() > 5;//判斷年齡是否大於5
        boolean boo=predicate.test(p1.get(1));
        // 字符串的非空判斷
        Predicate<String> predicateStr = x -> null == x || "".equals(x);
        System.out.println(predicateStr.test(""));//true
        //過濾年齡大於5的person 返回list
        List<Person> personList=p1.stream().filter(predicate).collect(Collectors.toList());
        List<Person> personList2=p1.stream().filter(person -> person.getAge()>5).collect(Collectors.toList());
        /**
         * map 類型轉換
         * <R> Stream<R> map(Function<? super T, ? extends R> mapper);
         * 這個方法傳入一個Function的函數式接口,這個接口,接收一個泛型T,返回泛型R,map函數的定義,返回的流,表示的泛型是R對象,
         * 這個表示,調用這個函數後,可以改變返回的類型,先看下面的案例
         */
        Function<Integer, String> function1 = x -> x +"www";//x爲傳入參數int類型  將它鏈接一個字符串 返回String類型
        String zw=function1.apply(5);//結果 5www
        //將p1中的年齡提取出來成一個list
        List<Integer> ages=p1.stream().map(person -> person.getAge()).collect(Collectors.toList());
        /**
         * flatMap操作
         * <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
         * 這個接口,跟map一樣,接收一個Fucntion的函數式接口,不同的是,Function接收的泛型參數,第二個參數是一個Stream流;方法,
         * 返回的也是泛型R,具體的作用是把兩個流,變成一個流返回,下面,我們看一個案例,來詳細解答,怎麼把兩個流的內容,
         * 變成一個流的內容
         */
        String[] strss = { "aaa", "bbb","ccc" };
        Arrays.stream(strss).map(str -> str.split("")).forEach(System.out::println);// java.lang.String;@53d8d10a
        List<String > w2=Arrays.stream(strss).map(str -> str.split("")).flatMap(Arrays::stream).collect(Collectors.toList());// aaabbbccc
        Arrays.stream(strss).map(str -> str.split("")).flatMap(str -> Arrays.stream(str)).forEach(System.out::println);// aaabbbccc
        /**
         * 去重複
         Stream<T> distinct();
         */
        //去重複後輸出
        p1.stream().distinct().forEach(System.out::println);
        /**
         * 排序
         Stream<T> sorted();
         根據屬性排序
         Stream<T> sorted(Comparator<? super T> comparator);
         */
        //排序 按person 中的age屬性排序
        p1.stream().sorted((p0,p2)->p0.getAge()-p2.getAge()).forEach(System.out::println);
        p1.stream().sorted(Comparator.comparing(person -> person.getAge())).forEach(System.out::println);
        p1.stream().sorted(Comparator.comparing(Person::getAge)).forEach(System.out::println);
        /**
         * 對對象的屬性進行操作
         Stream<T> peek(Consumer<? super T> action);
         */
        //對對像進行操作  把年齡大於2的人的名字加上 青年
        //p1.stream().filter(person -> person.getAge()>2).peek(person -> person.setName("青年"+person.getName())).forEach(System.out::println);
        /**
         *  截斷--取先maxSize個對象
         Stream<T> limit(long maxSize);
         截斷--忽略前N個對象
         Stream<T> skip(long n);
         */
        //截斷--取先maxSize個對象
         p1.stream().limit(2).forEach(System.out::println);
        //截斷--忽略前N個對象
        p1.stream().skip(2).forEach(System.out::println);

        /**
         long count();
         count方法,跟List接口的size一樣,返回的都是這個集合流的元素的長度,不同的是,流是集合的一個高級工廠,
         中間操作是工廠裏的每一道工序,我們對這個流操作完成後,可以進行元素的數量的和;
         boolean anyMatch(Predicate<? super T> predicate);
         boolean allMatch(Predicate<? super T> predicate);
         boolean noneMatch(Predicate<? super T> predicate);
         剩下的三個方法,傳入的都是Predicate的函數式接口
         anyMatch表示,判斷的條件裏,任意一個元素成功,返回true
         allMatch表示,判斷條件裏的元素,所有的都是,返回true
         noneMatch跟allMatch相反,判斷條件裏的元素,所有的都不是,返回true
         */
        //統計有幾個年齡==10的人
        long cou=p1.stream().filter(person -> person.getAge()==10).count();
        //判斷list中是否有年齡==2的person
       boolean si= p1.stream().anyMatch(person -> person.getAge()==2);//true
        //判斷list中是否有所有人年齡==2
       boolean si2= p1.stream().allMatch(person -> person.getAge()==2);//false
        //判斷list中是否有所有人年齡==2
        boolean si3= p1.stream().noneMatch(person -> person.getAge()==2);//false

        /**
         * 終端操作 toArray操作
         * public final <A> A[] toArray(IntFunction<A[]> generator)
         */
        List<String> st = Arrays.asList("a", "b", "c");
        String[] dd = st.stream().toArray(str -> new String[st.size()]);
        String[] dd1 = st.stream().toArray(String[]::new);
        Object[] obj = st.stream().toArray();

        String[] dd2 = st.toArray(new String[st.size()]);
        Object[] obj1 = st.toArray();
        //可以看到,前三個,是調用的stream的toArray的函數,以及一些用法,後面的兩個,是直接調用的List接口的toArray函數,List接口裏的

        /**
         * 終端操作 min,max,findFirst,findAny操作
         Optional<T> min(Comparator<? super T> comparator); //集合中的最小值
         Optional<T> max(Comparator<? super T> comparator); //集合中的最大值
         Optional<T> findFirst();  //返回集合中的第一個
         Optional<T> findAny();   //返回這個集合中,取到的任何一個對象
         */
        //Optional的get方法,是取到操作後的對象,
        List<Integer> integerList = Arrays.asList(1,5,8,3,9);
        //Optional min=integerList.stream().min((o1,o2)-> o1.compareTo(o2));
        Optional min=integerList.stream().min(Comparator.naturalOrder());
        Optional max=integerList.stream().max((o1,o2)-> o1.compareTo(o2));
        System.out.println("最小值"+min.get()+" 最大值-- "+max.get());
        //查詢list中年齡最小的person
        Optional aaa= p1.stream().min(Comparator.comparing(person -> person.getAge()));
        Person pmin=(Person)aaa.get();

        List<String> stringss = Arrays.asList("d", "b", "a", "c", "a");
        Optional<String> aa = stringss.stream().filter(str -> !str.equals("a")).findFirst();
        Optional<String> bb = stringss.stream().filter(str -> !str.equals("a")).findAny();
        Optional<String> aa1 = stringss.parallelStream().filter(str -> !str.equals("a")).findFirst();
        Optional<String> bb1 = stringss.parallelStream().filter(str -> !str.equals("a")).findAny();
        System.out.println(aa.get() + "===" + bb.get());// d===d
        System.out.println(aa1.get() + "===" + bb1.get());// d===b or d===c

        /**
         *終端操作reduce操作
         * reduce 是一種歸約操作,將流歸約成一個值的操作叫做歸約操作,用函數式編程語言的術語來說,這種稱爲摺疊(fold);
         T reduce(T identity, BinaryOperator<T> accumulator);
         這個函數,接受2個參數,第一個表示初始值,第二個值,傳入的是一個函數式接口BinaryOperator,這個接口繼承BiFunction;計算的表達式的規則;
         Optional<T> reduce(BinaryOperator<T> accumulator);
         這個接口。只用傳入計算規則,初始值是list的第一個參數,返回的optional對象,預防list裏,全部是null;
         <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
         */
        Integer hc = integerList.stream().reduce(0, (a, b) -> a + b);//求和  identity  初始值
        Optional<Integer> hc1 = integerList.stream().reduce((a, b) -> a + b);//求和
        Optional<Integer> hc11 = integerList.stream().reduce((a, b) -> a * b);//求乘積
        System.out.println(hc);
        System.out.println(hc1.get());

        /**
         * 終端操作 collect操作
         * <R> R collect(Supplier<R> supplier,BiConsumer<R, ? super T> accumulator,BiConsumer<R, R> combiner);
         <R, A> R collect(Collector<? super T, A, R> collector);
         第一個,是傳入3個參數的抽象方法,
         第二個只有一個參數的先看下stream中的collect操作Collectors靜態工廠類,而在這個靜態工廠類中,大部分的實現,
         都是調用的三個參數的方法,幾乎滿足了我們日常中所有的操作;所以說,我們只看下,這個靜態工廠類中,有哪些實現
         */
        //轉list
        List<String> nameList = p1.stream().map(p -> p.getName()).collect(Collectors.toList());
        //轉set
        Set<String> nameSet = p1.stream().map(p -> p.getName()).collect(Collectors.toSet());
        // 轉map,需要指定key和value,Function.identity()表示當前的Emp對象本身  原list中指定爲key的字段不能有重複
        Map<Integer,Person> personMap=p1.stream().collect(Collectors.toMap(p->p.getAge(),Function.identity()));
        //// 計算元素中的個數
        Long count = p1.stream().collect(Collectors.counting());
        // 數據求和 summingInt summingLong,summingDouble
        Integer sumAges = p1.stream().collect(Collectors.summingInt(Person::getAge));//Person::getAge   等價於p->p.getAge()
        // 平均值 averagingInt,averagingDouble,averagingLong
        Double aveAges = p1.stream().collect(Collectors.averagingInt(Person::getAge));
        // 綜合處理的,求最大值,最小值,平均值,求和操作
        // summarizingInt,summarizingLong,summarizingDouble
        IntSummaryStatistics intSummary = p1.stream().collect(Collectors.summarizingInt(Person::getAge));
        System.out.println(intSummary.getAverage());//
        System.out.println(intSummary.getMax());//
        System.out.println(intSummary.getMin());//
        System.out.println(intSummary.getSum());//
        /**
         * IntSummaryStatistics
         */
        IntSummaryStatistics stats=p1.stream().mapToInt(x->x.getAge()).summaryStatistics();
        System.out.println("列表中最大的數 : " + stats.getMax());
        System.out.println("列表中最小的數 : " + stats.getMin());
        System.out.println("所有數之和 : " + stats.getSum());
        System.out.println("平均數 : " + stats.getAverage());
        // 連接字符串,當然也可以使用重載的方法,加上一些前綴,後綴和中間分隔符
        String strEmp = p1.stream().map(emp -> emp.getName()).collect(Collectors.joining());
        String strEmp1 = p1.stream().map(emp -> emp.getName()).collect(Collectors.joining("-中間的分隔符-"));
        String strEmp2 = p1.stream().map(emp -> emp.getName()).collect(Collectors.joining("-中間的分隔符-", "前綴*", "&後綴"));
        // maxBy 按照比較器中的比較結果刷選 最大值
        Optional<Integer> maxAge = p1.stream().map(emp -> emp.getAge())
                .collect(Collectors.maxBy(Comparator.comparing(Function.identity())));
        // 最小值
        Optional<Integer> minAge = p1.stream().map(emp -> emp.getAge())
                .collect(Collectors.minBy(Comparator.comparing(Function.identity())));
        System.out.println("max:" + maxAge);
        System.out.println("min:" + minAge);
        // 歸約操作 求和
        Optional ot=p1.stream().map(emp -> emp.getAge()).collect(Collectors.reducing((x, y) -> x+ y));
        int rr=p1.stream().map(emp -> emp.getAge()).collect(Collectors.reducing(0, (x, y) -> x + y));

        List<Person> dq=new ArrayList();
        dq.add(new Person("廣州",10));
        dq.add(new Person("廣州",10));
        dq.add(new Person("北京",7));
        dq.add(new Person("北京",5));
        dq.add(new Person("武漢",6));
        dq.add(new Person("杭州",8));
        dq.add(new Person("上海",3));
        // 分操作 groupingBy 根據姓名,把原list進行分組
        Map<String, List<Person>> mapGroup = dq.stream().collect(Collectors.groupingBy(Person::getName));
        // partitioningBy 分區操作 需要根據類型指定判斷分區
        Map<Boolean, List<Integer>> partitioningMap = p1.stream().map(emp -> emp.getAge())
                .collect(Collectors.partitioningBy(age -> age > 5));
        System.out.println("");


    }

    private static List<Person> getPersonList(){
        List<Person> p=new ArrayList<>();
        Person rr=new Person("兒子2",10);
        Person rr1=new Person("兒子2",10);
        p.add(rr);
        //p.add(rr1);
        for (int i=0;i<8;i++){
            Person person=new Person("兒子"+i,i);
            p.add(person);
        }
        return p;
    }

}

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