Java8 Stream流的终端操作

2020-09-22  本文已影响0人  垃圾简书_吃枣药丸

中间操作不会消耗流,只是将一个流转换成另外一个流,类似于流水线。
终端操作会消耗流,以产生一个最终结果,终端操作完成后,流就被消耗了,不可再调用相关操作流的方法。

Collectors终端操作

一、 规约与汇总

1. 查找流中的最大值和最小值

public static void main(String[] args) {
    Random random = new Random();
    Optional<Integer> minVal = Stream.generate(() -> random.nextInt(1000))
            .limit(100)
            .collect(Collectors.minBy(Comparator.comparingInt(x -> x)));

    minVal.ifPresent(System.out::println);

    Optional<Integer> maxVal = Stream.generate(() -> random.nextInt(1000))
            .limit(100)
            .collect(Collectors.maxBy(Comparator.comparingInt(x -> x)));
    maxVal.ifPresent(x -> System.out.println("生成的最大随机值为: " + x));

    //或或或或或或或或或或或或或或或或或或或或
    Optional<Integer> maxVal2 = Stream.generate(() -> random.nextInt(1000))
            .limit(100)
            .max(Comparator.comparingInt(x -> x));
}

2. 求和,计算平均值与结果收集器

public void sumAvg() {
    Random random = new Random();
    // 生成1000范围内的数字的方法
    Supplier<Integer> integerSupplier = () -> random.nextInt(1000);
    // 生成1000个1000以内的数字,并返回一个列表
    List<Integer> integerList = Stream.generate(integerSupplier)
            .limit(1000)
            .collect(Collectors.toList());

    // 求和操作
    Integer sum = integerList.stream()
            .collect(Collectors.summingInt(x -> x));
    System.out.println("求和结果: " + sum);

    // 计算平均值操作
    Double avg = integerList.stream()
            .collect(Collectors.averagingDouble(x -> x));
    System.out.println("平均值为: " + avg);
}
求和结果: 514905
平均值为: 514.905
DoubleSummaryStatistics summaryStatistics = integerList.stream()
        .collect(Collectors.summarizingDouble(x -> x));

long count = summaryStatistics.getCount();
double average = summaryStatistics.getAverage();
double max = summaryStatistics.getMax();
double min = summaryStatistics.getMin();
double sumResult = summaryStatistics.getSum();

System.out.println(count);
System.out.println(average);
System.out.println(max);
System.out.println(min);
System.out.println(sumResult);
// XxxSummaryStatistics重写了toString()方法
System.out.println(summaryStatistics);
1000
514.905
999.0
0.0
514905.0
DoubleSummaryStatistics{count=1000, sum=514905.000000, min=0.000000, average=514.905000, max=999.000000}

3. 连接并返回字符串Collectors.join(delimiter)

public void joinDemo() {
    AppleStream chinaApple = new AppleStream(10, "中国");
    AppleStream usApple = new AppleStream(20, "米国");
    AppleStream koreaApple = new AppleStream(30, "韩国");

    String joinResult = Stream.of(chinaApple, usApple, koreaApple)
            // 需要将流转换成Stream<String>
            .map(AppleStream::toString)
            .collect(Collectors.joining(",", "【", "】"));
    System.out.println(joinResult);

    System.out.println(IntStream.rangeClosed(1, 20)
            .mapToObj(String::valueOf)
            .collect(Collectors.joining(",", "", "")));
}
【AppleStream(weight=10, country=中国),AppleStream(weight=20, country=米国),AppleStream(weight=30, country=韩国)】
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20

4. 自定义规约操作:广义上的规约汇总

public void reduceDemo() {
    Apple chinaApple = new Apple(10, "中国");
    Apple usApple = new Apple(20, "米国");
    Apple koreaApple = new Apple(30, "韩国");

    //重量最大的苹果
    Optional<Apple> maxWeightApple = Stream.<Apple>of(chinaApple, usApple, koreaApple)
            .collect(Collectors.reducing((x1, x2) -> x1.getWeight() > x1.getWeight() ? x1 : x2));
    maxWeightApple.ifPresent(System.out::println);

    // 最小的重量
    Integer minVal = Stream.of(chinaApple, usApple, koreaApple)
            .collect(Collectors.reducing(0, Apple::getWeight, Integer::min));
    System.out.println(minVal);

    // 质量总和
    Integer sumVal = Stream.of(chinaApple, usApple, koreaApple)
            .collect(Collectors.reducing(0, Apple::getWeight, Integer::sum));
    System.out.println(sumVal);
}

二、 分组


/**
 * 质量标准
 */
enum Quality {
    /**
     * 上乘
     */
    PERFECT,
    /**
     * 普通
     */
    NORMAL;
}

public void groupByDemo() {
    Apple chinaApple = new Apple(10, "中国");
    Apple usApple = new Apple(20, "米国");
    Apple koreaApple = new Apple(30, "韩国");
    Apple japanApple = new Apple(40, "日本");

    Map<Quality, List<Apple>> appleQualityMap = Stream.of(chinaApple, usApple, koreaApple, japanApple)
            .collect(Collectors.groupingBy(curApple -> {
                // 质量<=20为优秀,质量>20为一般
                if (curApple.getWeight() <= 20) {
                    return Quality.PERFECT;
                } else {
                    return Quality.NORMAL;
                }
            }));

    System.out.println(JSON.toJSONString(appleQualityMap, true));
}
{
  "NORMAL": [
    {
      "country": "韩国",
      "weight": 30
    },
    {
      "country": "日本",
      "weight": 40
    }
  ],
  "PERFECT": [
    {
      "country": "中国",
      "weight": 10
    },
    {
      "country": "米国",
      "weight": 20
    }
  ]
}
public void groupByDemo() {
    Apple chinaApple = new Apple(10, "中国");
    Apple chinaAppleEnhance = new Apple(100, "中国");
    Apple chinaAppleDoubleEnhance = new Apple(1000, "中国");

    Apple usApple = new Apple(20, "米国");

    Apple koreaApple = new Apple(30, "韩国");

    Apple japanApple = new Apple(40, "日本");
    Apple japanAppleEnhance = new Apple(80, "日本");
    Apple japanAppleDoubleEnhance = new Apple(120, "日本");

    Map<Quality, Map<String, List<Apple>>> appleQualityMap = Stream.of(chinaApple, chinaAppleEnhance, chinaAppleDoubleEnhance, usApple, koreaApple, japanApple, japanAppleEnhance, japanAppleDoubleEnhance)
            .collect(Collectors.groupingBy(curApple -> {
                // 质量<=20为优秀,质量>20为一般
                if (curApple.getWeight() <= 20) {
                    return Quality.PERFECT;
                } else {
                    return Quality.NORMAL;
                }
                // 再根据质量进行分组后再根据国家进行分组
            }, Collectors.groupingBy(Apple::getCountry)));


    System.out.println(JSON.toJSONString(appleQualityMap, true));
}
{
  "NORMAL": {
    "韩国": [
      {
        "country": "韩国",
        "weight": 30
      }
    ],
    "中国": [
      {
        "country": "中国",
        "weight": 100
      },
      {
        "country": "中国",
        "weight": 1000
      }
    ],
    "日本": [
      {
        "country": "日本",
        "weight": 40
      },
      {
        "country": "日本",
        "weight": 80
      },
      {
        "country": "日本",
        "weight": 120
      }
    ]
  },
  "PERFECT": {
    "米国": [
      {
        "country": "米国",
        "weight": 20
      }
    ],
    "中国": [
      {
        "country": "中国",
        "weight": 10
      }
    ]
  }
}

2. 按子组收集数据(指定用于处理子组数据的函数)

    public static <T, K> Collector<T, ?, Map<K, List<T>>>
    groupingBy(Function<? super T, ? extends K> classifier) {
        return groupingBy(classifier, toList());
    }

默认第二个参数是Collectors.toList(),实际上可以替换成我们需要的方法,如计算子组的数量:

public void groupByDemo() {
    Apple chinaApple = new Apple(10, "中国");
    Apple chinaAppleEnhance = new Apple(100, "中国");
    Apple chinaAppleDoubleEnhance = new Apple(1000, "中国");

    Apple usApple = new Apple(20, "米国");

    Apple koreaApple = new Apple(30, "韩国");

    Apple japanApple = new Apple(40, "日本");
    Apple japanAppleEnhance = new Apple(80, "日本");
    Apple japanAppleDoubleEnhance = new Apple(120, "日本");

    Map<Quality, Long> qualityLongMap = Stream.of(chinaApple, chinaAppleEnhance, chinaAppleDoubleEnhance, usApple, koreaApple, japanApple, japanAppleEnhance, japanAppleDoubleEnhance)
            .collect(Collectors.groupingBy(curApple -> {
                // 质量<=20为优秀,质量>20为一般
                if (curApple.getWeight() <= 20) {
                    return Quality.PERFECT;
                } else {
                    return Quality.NORMAL;
                }
                // 再根据质量进行分组后再计算每组的元素的个数
            }, Collectors.counting()));
    System.out.println(JSON.toJSONString(qualityLongMap, true));
}
{
  "PERFECT": 2,
  "NORMAL": 6
}
public void groupByDemo() {
    Apple chinaApple = new Apple(10, "中国");
    Apple usApple = new Apple(20, "米国");
    Apple koreaApple = new Apple(30, "韩国");
    Apple japanApple = new Apple(40, "日本");

    Map<Quality, String> qualityCountryMap = Stream.of(chinaApple, usApple, koreaApple, japanApple)
            .collect(Collectors.groupingBy(curApple -> {
                // 质量<=20为优秀,质量>20为一般
                if (curApple.getWeight() <= 20) {
                    return Quality.PERFECT;
                } else {
                    return Quality.NORMAL;
                }
                // 再将相应分组的国家的名字打印出来
            }, Collectors.mapping(Apple::getCountry, Collectors.joining(","))));
    System.out.println(JSON.toJSONString(qualityCountryMap, true));
}
{
  "PERFECT": "中国,米国",
  "NORMAL": "韩国,日本"
}

先要求: 先根据apple的weight进行分组,再将每组中weight最大的apple找出来,再返回每组最大的apple的weight,即返回Map<quality, maxWeight>

public void groupByDemo() {
    Apple chinaApple = new Apple(10, "中国");
    Apple usApple = new Apple(20, "米国");
    Apple koreaApple = new Apple(30, "韩国");
    Apple japanApple = new Apple(40, "日本");

    Map<Quality, Integer> qualityCountryMap = Stream.of(chinaApple, usApple, koreaApple, japanApple)
            .collect(Collectors.groupingBy(curApple -> {
                // 质量<=20为优秀,质量>20为一般
                if (curApple.getWeight() <= 20) {
                    return Quality.PERFECT;
                } else {
                    return Quality.NORMAL;
                }
            }, Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(Apple::getWeight)), (optionalApple) -> optionalApple.get().getWeight())));

    System.out.println(JSON.toJSONString(qualityCountryMap, true));
}
{
    "NORMAL":40,
    "PERFECT":20
}

三、分区 partitioningBy()

分区是分组的一种特殊情况,分区返回的Map的keys只有truefalse。其他用法与groupingBy基本一致。

public void partitioningByDemo() {
    Apple chinaApple = new Apple(10, "中国");
    Apple usApple = new Apple(20, "米国");
    Apple koreaApple = new Apple(30, "韩国");
    Apple japanApple = new Apple(40, "日本");

    Map<Boolean, String> appleQualityCountryMap = Stream.of(chinaApple, usApple, koreaApple, japanApple)
            //以质量20为分界线进行分区,将分区之后的apple的原产地的国家返回
            .collect(Collectors.partitioningBy(x -> x.getWeight() > 20, Collectors.mapping(Apple::getCountry, Collectors.joining(","))));
    System.out.println(JSON.toJSONString(appleQualityCountryMap, true));
}
{
  "false": "中国,米国",
  "true": "韩国,日本"
}

> 如何自定义Collector?

上一篇 下一篇

猜你喜欢

热点阅读