【问题标题】:Java streams: count distinct values in array of primitivesJava流:计算基元数组中的不同值
【发布时间】:2020-01-03 19:16:38
【问题描述】:

为什么 int 数组的不同计数返回的结果与 Integer 数组的计数不同?在这两种情况下,我都希望得到 3 的结果。

int[] numbers1 = { 1, 2, 3 };
System.out.println("numbers1: " + Arrays.toString(numbers1));
System.out.println("distinct numbers1 count: " + Stream.of(numbers1).distinct().count());

Integer[] numbers2 = { 1, 2, 3 };
System.out.println("numbers2: " + Arrays.toString(numbers2));
System.out.println("distinct numbers2 count: " + Stream.of(numbers2).distinct().count());

结果

numbers1: [1, 2, 3]
distinct numbers1 count: 1

numbers2: [1, 2, 3]
distinct numbers2 count: 3

【问题讨论】:

    标签: java algorithm math java-8 java-stream


    【解决方案1】:

    因为在第一个Stream.of 方法中将整个数组视为一个元素 - 它创建一个包含数组元素的流。要使用基元数组,您必须改用 Arrays.stream

    【讨论】:

    • 我会使用Arrays.stream 流式传输现有数组一般。然后,你就不用再考虑了。 Stream 类中的工厂方法用于 varargs 用例,即当您使用Stream.of(a)Stream.of(a, b)Stream.of(a, b, c) 等时,您也不需要想想这些调用之一有一个专门的版本......
    【解决方案2】:

    替换

    Stream.of(numbers1)
    

    Arrays.stream(numbers1)
    

    正确地将int[] 转换为IntStream 而不是Stream<int[]>

    【讨论】:

      【解决方案3】:

      在您的第一种情况下,Stream.of(numbers1) 的类型是 Stream<int[]>,它只有一个值。

      在第二种情况下,Stream.of(numbers2) 的类型是 Stream<Integer>,其中包含 3 个不同的值。

      您可以使用IntStream.of(1, 2, 3) 获取原始int 流。

      【讨论】:

        【解决方案4】:

        第一个Stream.of 返回一个Stream<int[]>,您有1 个不同的int[],称为numbers1。第二个Stream.of 返回一个Stream<Integer>,你有3 个不同的Integers,它们是123。在第一次调用Stream.of 时,您可以通过将Stream.of 替换为Arrays.stream 来解决此问题,因为Arrays 有一个专门的实用方法,采用int[] 并返回IntStream

        【讨论】:

          【解决方案5】:

          Streams 提供了两个静态的Stream<T> of() 方法:

          public static<T> Stream<T> of(T t) {..}
          

          public static<T> Stream<T> of(T... values) {..}
          

          第一种方法创建一个由单个对象组成的流,该对象作为参数提供,而第二种方法创建一个由数组元素组成的流。
          在您的情况下,int[] 参数使of(T values) 被调用,而Integer[] 参数使of(T... values) 被调用。
          预期的结果是1,然后是3

          为什么编译器不将两个调用绑定到同一个of() 方法?

          因为当传递的参数的声明类型是对象数组时,编译器会选择最具体的可用方法:of(T... values)
          但是当传递的参数的声明类型是原始数组时,该方法不匹配:int 不是Object。所以编译器可以选择的剩余方法是of(T t)

          长话短说:要流式传输基元数组,不要使用Stream.of(),而是使用专门为IntStream.of()DoubleStream.of() 设计的类。

          【讨论】:

          • 或者也可以使用Arrays.stream
          猜你喜欢
          • 2015-12-03
          • 1970-01-01
          • 1970-01-01
          • 2021-10-19
          • 2012-11-14
          • 1970-01-01
          • 2017-12-28
          • 2018-01-17
          • 2018-02-26
          相关资源
          最近更新 更多