stream

张碧晨發表於2024-09-26

注:List.of()方法需要1.8以上才支援

1.filter,過濾,關鍵:Predicate

 Stream.of(
                        new Fruit("草莓", "", "1", "red"),
                        new Fruit("香蕉", "", "2", "yellow"),
                        new Fruit("蘋果", "", "3", "green"),
                        new Fruit("橘子", "", "4", "orange"),
                        new Fruit("榴蓮", "", "5", "yellow")
                ).filter(fruit -> fruit.getColor().equals("red"))
                .forEach(System.out::println);

2.map,對映,關鍵:Function

Stream.of(
                        new Fruit("草莓", "", "1", "red"),
                        new Fruit("香蕉", "", "2", "yellow"),
                        new Fruit("蘋果", "", "3", "green"),
                        new Fruit("橘子", "", "4", "orange"),
                        new Fruit("榴蓮", "", "5", "yellow")
                ).map(Fruit::getColor)
                .forEach(System.out::println);

3.flatMap,扁平化(降維)

Stream.of(
List.of(new Fruit("葡萄", "", "1", "red"),
new Fruit("橙子", "", "2", "yellow"),
new Fruit("火龍果", "", "3", "green"),
new Fruit("橘子", "", "4", "orange")),
List.of(new Fruit("香蕉", "", "2", "yellow"),
new Fruit("蘋果", "", "3", "green"),
new Fruit("榴蓮", "", "5", "yellow"))
).flatMap(list -> list.stream())
.forEach(System.out::println);

Integer[][] arr = {
{1, 2, 3},
{3, 4, 5},
{5, 6, 7},
};
Arrays.stream(arr).flatMap(array -> Arrays.stream(array))
.forEach(System.out::println);
 

4.構建流

4.1 從集合構建

集合.stream()

4.2 從陣列構建

Arrays.stream(陣列)

4.3 從物件構建

Stream.of(物件)

        //從集合構建
        Arrays.stream(arr).flatMap(array -> Arrays.stream(array))
                .forEach(System.out::println);
        ArrayList<String> list = new ArrayList<>();
        HashSet<String> set = new HashSet<>();
        HashMap<String, String> map = new HashMap<>();
        list.stream().forEach(System.out::println);
        set.stream().forEach(System.out::println);
        map.entrySet().stream().forEach(System.out::println);
        //從陣列構建
        int[] array = {1, 2, 3, 4, 5, 6, 7, 8};
        Arrays.stream(array).forEach(System.out::println);
        //從物件構建
        Stream.of(1, 2, 3, 4, 5).forEach(System.out::println);    

合併和擷取

     //合併
        Stream<Integer> integerStream1 = Stream.of(1, 2, 3);
        Stream<Integer> integerStream2 = Stream.of(4, 5, 6);
        Stream<Integer> concat = Stream.concat(integerStream1, integerStream2);
        concat.forEach(System.out::println);
        //擷取
        //skip(long n) 跳過n個資料,保留剩下的
        //limit(long n) 保留n個資料,剩下的不要
        concat.skip(2).forEach(System.out::println);
        concat.limit(2).forEach(System.out::println);
        concat.skip(2).limit(2).forEach(System.out::println);

    //擷取根據條件確定擷取位置
    //takeWhile(Predicate p) 條件成立保留,一旦條件不成立,剩下的不要
    //dropWhile(Predicate p) 條件成立捨棄,一旦條件不成立,剩下的保留
    //concat.takeWhile(x->x<3).forEach(System.out::println);
    //concat.dropWhile(x->x<3).forEach(System.out::println);

生成流,不用現有資料生成stream物件

    //生成流,不用現有資料生成stream物件
        //1 簡單生成
        //IntStream.range(...)
        IntStream.range(1, 10).forEach(System.out::println);
        IntStream.rangeClosed(1, 9).forEach(System.out::println);
        //2 依賴上一個值生成當前值
        //IntStream.iterate(...) 1,3,5,7,9
        IntStream.iterate(1, x -> x + 2).limit(10).forEach(System.out::println);
        //3 不依賴上一個值生成當前值
        //IntStream.generate(...)
        IntStream.generate(() -> ThreadLocalRandom.current().nextInt(100)).limit(5).forEach(System.out::println);
        //生成隨機整數
        ThreadLocalRandom.current().ints(5, 0, 100).forEach(System.out::println);

查詢與判斷

        //查詢與判斷
        //查詢
        //filter(Predicate p).findAny() 找到任意一個元素
        //filter(Predicate p).findFirst() 找到第一個元素
        //判斷
        //1 anyMatch(Predicate p) 一個滿足
        //2 allMatch(Predicate p) 都滿足
        //3 noneMatch(Predicate p) 都不滿足
        IntStream intStream = IntStream.of(1, 2, 3, 4, 5, 6, 7);
        System.out.println(intStream.filter(x -> (x & 1) == 0).findFirst().orElse(-1));
        System.out.println(intStream.filter(x -> (x & 1) == 0).findAny().orElse(-1));
        System.out.println(intStream.anyMatch(x -> (x & 1) == 0));
        System.out.println(intStream.allMatch(x -> (x & 1) == 0));
        System.out.println(intStream.noneMatch(x -> (x & 1) == 0));

去重排序

     //去重
        IntStream.of(1, 2, 3, 1, 2, 4, 5, 6, 7, 1, 2)
                .distinct()
                .forEach(System.out::println);
        //排序
        Stream.of(
                        new Hero("張三", 90),
                        new Hero("李四", 98),
                        new Hero("王老五", 93),
                        new Hero("令狐沖", 95),
                        new Hero("東方不敗", 99),
                        new Hero("風清揚", 88),
                        new Hero("獨孤求敗", 82),
                        new Hero("任我行", 99)
//                ).sorted((a, b) -> a.getStrength() < b.getStrength() ? -1 : a.getStrength() == b.getStrength() ? 0 : 1)
//                ).sorted((a, b) -> Integer.compare(a.getStrength(), b.getStrength()))
//                ).sorted(Comparator.comparingInt(x-> x.getStrength())
//                ).sorted(Comparator.comparingInt(Hero::getStrength))
                ).sorted(Comparator.comparingInt(Hero::getStrength).reversed().thenComparing(x -> x.getName().length()))
                .forEach(System.out::println);
    }

化簡,兩兩合併,只剩一個

適合,最大值,最小值,求和,求個數

        //化簡,兩兩合併,只剩一個
        //適合,最大值,最小值,求和,求個數
        //reduce((p, x)->r)) p上次的合併結果,x當前元素,r本次合併結果
        //reduce(init,(p, x)->r))
        //reduce(init,(p, x)->r),(r1,r2)->r)
        Stream<Hero> heroStream = Stream.of(
                new Hero("張三", 90),
                new Hero("李四", 98),
                new Hero("王老五", 93),
                new Hero("令狐沖", 95),
                new Hero("東方不敗", 99),
                new Hero("風清揚", 88),
                new Hero("獨孤求敗", 82),
                new Hero("任我行", 99)
        );
        //最大值
        Optional<Hero> reduce = heroStream.reduce((h1, h2) -> h1.getStrength() > h2.getStrength() ? h1 : h2);
        System.out.println(reduce);
        Hero hero = heroStream.reduce(new Hero("-", -1), (h1, h2) -> h1.getStrength() > h2.getStrength() ? h1 : h2);
        System.out.println(hero);
        //求總數
        System.out.println(heroStream.map(h -> 1).reduce(0, (a, b) -> a + b));
        long count = heroStream.count();
        Optional<Hero> max = heroStream.max(Comparator.comparingInt(Hero::getStrength));
        Optional<Hero> min = heroStream.min(Comparator.comparingInt(Hero::getStrength));
        int sum = heroStream.mapToInt(Hero::getStrength).sum();
        OptionalDouble average = heroStream.mapToInt(Hero::getStrength).average();

收集

 //收集,將元素收集入容器
        //.collect(()->c,(c,x)->void)
        // ()->c  建立容器
        // (c,x)->void  將元素x放入容器c
        Stream<String> stringStream = Stream.of("張三", "李四", "王老五", "令狐沖", "東方不敗", "風清揚", "獨孤求敗", "任我行");
        ArrayList<String> result = stringStream.collect(() -> new ArrayList<>(), (list, x) -> list.add(x), (a, b) -> {});
        ArrayList<String> result = stringStream.collect(ArrayList::new, ArrayList::add, (a, b) -> {});
        LinkedHashSet<String> result = stringStream.collect(LinkedHashSet::new, Set::add, (a, b) -> {});
        HashMap<String, Integer> result = stringStream.collect(HashMap::new, (map, x) -> map.put(x, 1), (a, b) -> {
        });
        for (Map.Entry<String, Integer> str : result.entrySet()
        ) {
            System.out.println(str.getKey()+"  "+str.getValue());
        }

        StringBuilder collect = stringStream.collect(StringBuilder::new, StringBuilder::append, (a, b) -> {});
        System.out.println(collect);
        StringJoiner collect = stringStream.collect(() -> new StringJoiner(","), StringJoiner::add, (a, b) -> {});
        System.out.println(collect);

Collectos收集器

        List<String> collect = stringStream.collect(Collectors.toList());
        Set<String> collect1 = stringStream.collect(Collectors.toSet());
        String collect2 = stringStream.collect(Collectors.joining());
        String collect3 = stringStream.collect(Collectors.joining(","));

        for (String s:collect
             ) {
            System.out.println(s);
        }
        Map<String, Integer> collect4 = stringStream.collect(Collectors.toMap(x -> x, x -> 1));
        for (Map.Entry<String, Integer> str : collect4.entrySet()
        ) {
            System.out.println(str.getKey()+"  "+str.getValue());
        }

下游收集器

        //內層的收集器:下游收集器
        Map<Integer, java.util.List<String>> collect5 = stringStream.collect(Collectors.groupingBy(x -> x.length(), Collectors.toList()));
        for (Map.Entry<Integer, java.util.List<String>> str : collect5.entrySet()
        ) {
            System.out.println(str.getKey()+"  "+str.getValue());
        }
        Map<Integer, String> collect6 = stringStream.collect(Collectors.groupingBy(x -> x.length(), Collectors.joining(",")));
        for (Map.Entry<Integer, String> str : collect6.entrySet()
        ) {
            System.out.println(str.getKey()+"  "+str.getValue());
        }
        //mapping(x->y,dc)
        Map<Integer, java.util.List<Integer>> collect =
                heroStream.collect(Collectors.groupingBy(h -> h.getName().length(), Collectors.mapping(h -> h.getStrength(), Collectors.toList())));
        for (Map.Entry<Integer, java.util.List<Integer>> str : collect.entrySet()
        ) {
            System.out.println(str.getKey()+"  "+str.getValue());
        }

基本流

        IntStream intStream = IntStream.of(1, 2, 3, 4, 5, 6);
        LongStream longStream = LongStream.of(1L, 2L, 3L);
        DoubleStream doubleStream = DoubleStream.of(1.0, 2.0, 3.0);
        System.out.println(intStream.sum());
        System.out.println(intStream.min());
        System.out.println(intStream.max());
        System.out.println(intStream.average());
        IntSummaryStatistics intSummaryStatistics = intStream.summaryStatistics();
        System.out.println(intSummaryStatistics.getSum());
        System.out.println(intSummaryStatistics.getMax());
        System.out.println(intSummaryStatistics.getMin());
        System.out.println(intSummaryStatistics.getCount());
        System.out.println(intSummaryStatistics.getAverage());

stream 流的特性

1.一次使用

流只能被消費一次

2.兩類操作

(中間操作lazy,終結操作eager)

並行流

資料量問題:資料量大時才推薦並行流。

執行緒會無限增加嗎:跟cpu能處理的執行緒數相關

收尾的意義:轉不可變集合,stringbuilder轉string

是否執行緒安全:不會有執行緒安全問題

        java.util.List<Integer> collect = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
                .parallel()
                .collect(Collector.of(
                        () -> new ArrayList(),  //如何建立容器
                        (list, x) -> list.add(x),//如何向容器新增資料
                        (list1, list2) -> {
                            list1.addAll(list2);
                            return list1;
                        },//如何合併兩個容器的資料
                        list -> list
                        //特性:容器是否支援併發,是否需要收尾,是否需要保持收集順序
                ));

特性:容器是否支援併發(預設不支援),是否需要收尾(預設收尾),是否需要保持收集順序(預設保證)