Java8的流特性-經常使用操做(例)

public class StreamMethods {
    /**
     * 流的過濾
     * 大部分流操做的結果仍然是一個流,因此咱們能夠鏈式調用
     */
    public void testStreamFilter() {
        List<Integer> integers = new ArrayList<>();
        integers.addAll(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8));
        //使用流類庫
        integers = integers.stream().filter(i -> i > 5).collect(Collectors.toList());
        System.out.println(integers);
    }

    /**
     * 流的映射
     *  相似於SQL中的select,能夠將一組元素轉換成另外一種元素。
     *  下面的例子將一組整數轉換爲平方。這是一個簡單的例子,實際場合中經常須要將一組對象流轉換爲另外一組對象。
     */
    public void testStreamMap() {

        List<Integer> integers = Stream.of(1, 2, 3, 4)
                .map(i -> i * i)
                .collect(Collectors.toList());
        System.out.println(integers);
    }

    /**
     * 流的平整映射
     *  有時候須要將多個流的結果合併爲一個流,這時候須要使用平整映射。
     */
    public void testStreamFlatMap() {
        List<Integer> integers = Stream.of(Arrays.asList(1, 2, 3, 4), Arrays.asList(5, 6))
                .flatMap(n -> n.stream())
                .collect(Collectors.toList());
        System.out.println(integers);
    }

    /**
     * 流求最大或最小值
     */
    public void testStreamMaxOrMin() {

        int min = Stream.of(1, 23, 4, 50, 8888)
                .min(Comparator.comparingInt(i -> i))
                .get();
        int max = Stream.of(0, 1, 2, 5, 89, 465, 45, 666, 8888)
                .max(Comparator.comparingInt(i -> i)).get();
        System.out.println(String.format("max:%d,min:%d", max, min));
    }


    /**
     * TODO 不太懂這個接口 流的通用迭代 reduce
     */
    public void testStreamReduce() {

        int sum = Stream.of(1, 2, 3, 4, 5)
                .reduce((acc, e) -> acc + e).get();
        System.out.println(String.format("sum:%d", sum));

        int product = Stream.of(1, 2, 3, 4, 5)
                .reduce(1, (acc, e) -> acc * e);
        System.out.println(String.format("product:%d", product));
    }

    /**
     * 流的一些謂詞特性
     * allMatch:當全部條件知足時返回true
     * anyMatch:只要有一個元素知足就返回true
     * noneMatch:當沒有元素返回時返回true
     * distinct:去掉重複的元素
     * limit:保留流的前幾個元素
     * skip:跳過前幾個元素而獲取以後的全部元素
     */
    public void testStreamPredicate() {
        boolean allMatch = Stream.of(1, 2, 3, 4, 5).allMatch(i -> i > 3);
        System.out.println("allMatch: " + allMatch);

        boolean anyEqual = Stream.of(1, 2, 3, 4, 5).anyMatch(i -> i >= 2);
        System.out.println("anyMatch: " + anyEqual);

        boolean noneEqual = Stream.of(1, 2, 3, 4, 5).noneMatch(i -> i < 0);
        System.out.println("noMatch: " + noneEqual);

        List<Integer> list = Stream.of(1, 2, 3, 4, 2, 2, 4, 3, 1, 2, 4, 3, 1, 2)
                .distinct()
                .collect(Collectors.toList());
        System.out.println(list);

        String list1 = Stream.of(1, 2, 3, 4, 5, 6)
                .limit(3)
                .map(String::valueOf)
                .collect(Collectors.joining(", ", "[", "]"));
        System.out.println(list1);

        String list2 = Stream.of(1, 2, 3, 4, 5, 6)
                .skip(3)
                .map(String::valueOf)
                .collect(Collectors.joining(", ", "[", "]"));
        System.out.println(list2);
    }

    /**
     * 基本類型流
     * 因爲Java存在一個基本類型裝箱拆箱的過程,因此會有性能開銷。
     * 爲了不這些開銷,流類庫針對常見的基本類型int、long、double作了特殊處理,
     * 爲它們單獨準備了一些類和方法。
     * 注意:對於一些方法也有基本類型的版本,能夠將一個對象流轉換爲對應的基本類型,
     * 這些方法的命名規則是方法名+To+基本類型。若是須要處理大量數據的基本類型流,
     * 能夠考慮使用這些方法。
     */
    public void testStreamPrimitiveType() {

        IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
        LongStream longStream = LongStream.of(1, 2, 3, 4, 5);
        DoubleStream doubleStream = DoubleStream.of(10, 2.0, 3.0);

        int sum = Stream.of(1, 2, 3, 4, 5)
                .mapToInt(i -> i)
                .reduce(0, (acc, e) -> acc + e);
        //.sum();
        System.out.println("sum :" + sum);
    }

    /**
     * 流的收集器(collect()方法)
     *   使用流類庫的最後一步就是將流轉換爲咱們須要的集合了,這就須要用到收集器。
     *   收集數據的最後一步須要調用collect方法,它的參數是java.util.stream.Collector類的靜態方法。
     *   聽起來是否是有點奇怪,實際上,接受的是這些方法的返回值。
     *   例如toList()方法其實是這樣的,返回的是Collector對象,而後由collect方法處理,獲取最後的集
     *   合。
     *   源代碼示例
     *   public static <T>Collector<T, ?, List<T>> toList() {
     *     return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
     *     (left, right) -> { left.addAll(right); return left; },
     *     CH_ID);
     *    }
     */

    /**
     * 經過收集器得到流的集合
     */
    public void testGetStreamCollections(){
        List<Integer> integers = Stream.of(1,2,3,4,5)
                .collect(Collectors.toList());
        System.out.println("list: "+integers);

        Set<Integer> set = Stream.of(1,2,2,3,4,5)
                .collect(Collectors.toSet());
        System.out.println("set: "+set);

        //使用本身但願的集合(能夠構形成map集合或concurrentMap集合)
        ArrayList<Integer> integerArrayList = Stream.of(1,2,3)
                .collect(Collectors.toCollection(ArrayList::new));
        System.out.println("integerArrayList: "+integerArrayList);

    }

    /**
     * 經過收集器獲取流的值
     *   收集器不只能夠得到集合,還能夠由流獲取一個值,
     *   這能夠經過調用maxBy、minBy、averageXXX和summingXXX方法來實現
     */
    public void testGetStreamValue(){
        int max = Stream.of(1,2,3,4)
                .collect(Collectors.maxBy(Comparator.comparing(i->i)))
                .get();
        int min = Stream.of(1,2,3,4)
                .collect(Collectors.minBy(Comparator.comparing(i->i)))
                .get();
        double average = Stream.of(1,2,3,4)
                .collect(Collectors.averagingInt(Integer::intValue));
        int sum = Stream.of(1,2,3,4)
                .collect(Collectors.summingInt(i->i));
        System.out.println(
                String.format("max:%d,min:%d,average:%f,sum:%d", max, min, average, sum));

        /**
         * 有時候須要將流的數據組合爲一個字符串,這須要joining收集器,它的三個參數分別是分隔符、前綴和後綴。
         * 固然因爲它須要字符序列,因此這裏還須要用map方法將整數流轉換爲字符串流。
         */
        String string = Stream.of(1,2,3,4,5)
                .map(String::valueOf)
                .collect(Collectors.joining(", ","[","]"));
        System.out.println("string :"+string);

        /**
         * 還有一個簡單的收集器,做用就是計數,須要注意的是計數返回的結果是long類型就好了。
         * 這個收集器的主要做用是和其餘收集器一塊兒完成複雜的功能。
         */
        Long count = Stream.of(1,2,3,4,5,6,7,8)
                .collect(Collectors.counting());
               // .count();
        System.out.println("count: "+count);
    }

    /**
     * 流的數據分塊
     */
    public void testStreamDataPartition() {
        Map<Boolean, List<Integer>> map = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
                .collect(Collectors.partitioningBy(i -> i % 2 == 0));
        System.out.println("map: " + map);
    }

    /**
     * 流的數據分組
     *   相似於SQL中的group by語句。下面的例子將流按照數組個位數分爲好幾組
     */
    public void testDataGrouping() {
        Map<Integer, List<Integer>> map = Stream.of(21, 32, 43, 54, 11, 33, 22)
                .collect(Collectors.groupingBy(i -> i % 10));
        System.out.println("map: "+map);
    }

    /**
     * 流的組合收集器
     *   若是問題比較複雜,還能夠將多個收集器組合起來使用,一些收集器有重載的版本,支持第二個收集器,
     *   能夠用來實現這個功能。就拿前面那個數據分組的例子來講,此次我不只要分組,
     *   並且只須要每組的十位數字,那麼就能夠這樣寫。
     *   groupingBy的第二個參數可使用mapping收集器,mapping這裏的做用和流操做的map相似,
     *   將流再次進行映射,而後收集結果做爲最後Map的鍵值對。
     */
    public void testGroupCollect(){

        //按個位數字進行分組,而後只獲取十位上的數字
        Map<Integer, List<Integer>> map = Stream.of(21, 32, 43, 54, 11, 33, 22)
                .collect(Collectors.groupingBy(i -> i % 10,
                        Collectors.mapping(i -> i / 10,Collectors.toList())));
        System.out.println("map: "+map);

        //按個位數字分組,而後而後求各組的和
        Map<Integer,Integer> map1 = Stream.of(21,32,43,54,11,33,22)
                .collect(Collectors.groupingBy(i->i%10,Collectors.summingInt(i->i)));
        System.out.println("map1: "+map1);
    }


    /**
     * 關於流的其它特性
     */
    public void testOther(){

        /**
         * *   全部的流操做都是惰性的,也就是說直到最後調用收集器的時候,整個流操做纔開始進行。
         *   在這以前,你的流操做只不過相似於SQL的執行計劃,這時候尚未真正執行程序。因此下面的代碼什麼都不會輸出。
         */
        Stream.of(1,2,3,4,5)
                .filter(i->i>1)
                .filter(i->{
                    System.out.println("i: "+i);
                    return i<=3;
                });

        /**
         * 若是進行了不少流操做,流類庫會不會對流進行屢次迭代,致使程序速度很慢呢?
         * 這個擔憂也是多餘的,流類庫通過優化,會保證迭代以最少的次數進行。
         * 因此下面的代碼輸出結果是122334455,這說明流只迭代了一次。
         */
        List<Integer> integers = Stream.of(1, 2, 3, 4, 5)
                .filter(i -> {
                    System.out.print(i);
                    return i > 1;
                })
                .filter(i -> {
                    System.out.print(i);
                    return i <= 3;
                })
                .collect(Collectors.toList());
        System.out.println(integers);
    }

    /**
     * 流的循環
     */
    public void testForLoop(){

        /**
         * 流的循環,至關於for循環
         */
        IntStream.range(0, 3)
                .forEach(i -> System.out.print(i));

    }

    /**
     * 流的數據並行化
     *   須要注意並非說並行化以後,速度就必定會比串行化快,
     *   這須要根據當前系統、機器、執行的數據流大小來進行綜合評估。
     *   ArrayList這類容器就比較容易並行化,而HashMap並行化就比較困難。
     */
    public void testStreamParallel(){

        List<Integer> integers = IntStream.range(1, 101)
                .parallel()
                .filter(i -> i % 2 == 0)
                .boxed()
                .collect(Collectors.toList());
        System.out.println("integers :"+integers);
    }
}
相關文章
相關標籤/搜索