【问题标题】:Collecting value of int array using normal JAVA Stream使用普通 JAVA Stream 收集 int 数组的值
【发布时间】:2019-08-14 17:52:29
【问题描述】:

在我的程序中,我尝试使用流打印排序的 int 数组。但是我在使用普通流时得到了错误的输出。并且在使用 int 流时会打印出正确的详细信息。

请参阅下面的核心 sn-p 了解更多详细信息。

package com.test.sort.bubblesort;

import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class BubbleSortWithRecursion {

    public static void bubbleSort(int[] arr, int n) {

        if (n < 2) {
            return;
        }

        int prevValue;
        int nextValue;
        for (int index = 0; index < n-1; index++) {
            prevValue = arr[index];
            nextValue = arr[index+1];

            if  (prevValue > nextValue) {
                arr[index] = nextValue;
                arr[index+1] = prevValue;
            }
        }

        bubbleSort(arr, n-1);
    }

    public static void main(String[] args) {
        int arr[] = new int[] {10,1,56,8,78,0,12};
        bubbleSort(arr, arr.length);

        **//False Output** :  [I@776ec8df
        String output = Arrays.asList(arr)
            .stream()
            .map(x -> String.valueOf(x))
            .collect(Collectors.joining(","));

        System.out.println(output);

        //Correct Output : 0,1,8,10,12,56,78
        String output2 = IntStream
            .of(arr)
            .boxed()
            .map(x -> Integer.toString(x))
            .collect(Collectors.joining(","));

        System.out.println(output2);

    }


}

我在控制台上得到以下输出:

[I@776ec8df
0,1,8,10,12,56,78

第一行输出是使用正常的java流生成的,这是不正确的。

为什么我使用普通的 JAVA 流会收到虚假内容?我在这里错过了什么吗?

【问题讨论】:

    标签: java arrays java-8 java-stream


    【解决方案1】:

    你可以做得更短一点:

    String output = Arrays.stream(arr)
            .mapToObj(String::valueOf)
            .collect(Collectors.joining(","));
    

    结果是0,1,8,10,12,56,78

    首先你创建一个IntStream,然后你得到一个Stream&lt;String&gt;,它被收集到最终的String

    【讨论】:

      【解决方案2】:

      Arrays.asList(arr) 返回一个 List&lt;int[]&gt;,其唯一元素是 arr。因此流式传输List,然后将该单个元素映射到String.valueOf(x) 并使用Collectors.joining(",") 收集将产生一个String,其值是该单个数组的toString(),这是您看到的输出。

      String output = Arrays.asList(arr) // List<int[]>
          .stream() // Stream<int[]>
          .map(x -> String.valueOf(x)) // Stream<String> having a single element - "[I@776ec8df"
          .collect(Collectors.joining(",")); // "[I@776ec8df"
      

      当您从 int 数组创建 IntStream 时,您会获得单个元素的流(int 值),因此您可以将它们装箱,然后转换为 Strings 并将它们连接到得到想要的输出。

      如果你改变,你可以让你的第一个 sn-p 工作:

      int arr[] = new int[] {10,1,56,8,78,0,12};
      

      到:

      Integer arr[] = new Integer[] {10,1,56,8,78,0,12};
      

      因为这种方式Arrays.asList(arr) 将产生一个包含输入数组的所有元素的List&lt;Integer&gt;

      【讨论】:

      • 感谢您分享答案。我仍然有一个困惑。 Arrays.asList 在使用原始类型时生成 List。它不应该在使用包装器类型时产生 List 吗?
      • @GunjanShah 更好地理解它,Integer 是一个 Object,int 只是一个原生类型,所以当你使用原生类型的数组时,它可以被视为一个 Object,而不是 Integer 的数组,它被认为是对象数组
      • @GunjanShah 签名是static &lt;T&gt; List&lt;T&gt; asList(T... a)。 T 必须是引用类型,因此如果您传递原始数组,则数组本身就是该引用类型。如果传入某个引用类型的数组(比如Integer数组),T就变成了数组的元素类型(Integer)。
      • 哇...这看起来很简单,但这里隐藏着非常好的概念。这个答案帮助我使我的可变参数概念更加清晰。谢谢!
      【解决方案3】:

      你可以这样解决你的问题:

      String output = Arrays.stream(arr)
              .boxed()
              .map(String::valueOf)
              .collect(Collectors.joining(",")); // 0,1,8,10,12,56,78
      

      解释发生了什么:

      当您使用Arrays.asList() 时:

      public static <T> List<T> asList(T... a) {
          return new ArrayList<>(a);
      }
      

      它采用了T 类型的可变参数,在您的情况下,您将它用于int[] 对象,因此Arrays.asList() 将返回Listint[] 而不是整数流,因此您必须使用Arrays.stream 看起来像这样:

      public static IntStream stream(int[] array) {
          return stream(array, 0, array.length);
      }
      

      获取正确的数据。

      【讨论】:

      • 非常感谢您在这里分享建议。您的答案与 Eran 的答案相似,但在 Eran 的答案中更清楚地解释了 Varargs 映射解释。所以接受答案。
      猜你喜欢
      • 2017-04-19
      • 2020-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多