Java 从数组流式传输时,为什么不能将整数映射到字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29028980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:13:31  来源:igfitidea点击:

Why can't I map integers to strings when streaming from an array?

javafunctional-programmingjava-8java-stream

提问by Denys Séguret

This code works (taken in the Javadoc):

此代码有效(取自 Javadoc):

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
String commaSeparatedNumbers = numbers.stream()
    .map(i -> i.toString())
    .collect(Collectors.joining(", "));

This one can't be compiled:

这个不能编译:

int[] numbers = {1, 2, 3, 4};
String commaSeparatedNumbers = Arrays.stream(numbers)
    .map((Integer i) -> i.toString())
    .collect(Collectors.joining(", "));

IDEA tells me I have an "incompatible return type String in lambda expression".

IDEA 告诉我我在 lambda 表达式中有一个“不兼容的返回类型字符串”。

Why ? And how to fix that ?

为什么 ?以及如何解决这个问题?

采纳答案by assylias

Arrays.stream(int[])creates an IntStream, not a Stream<Integer>. So you need to call mapToObjinstead of just map, when mapping an intto an object.

Arrays.stream(int[])创建一个IntStream,而不是一个Stream<Integer>。因此,在将 an 映射到对象时,您需要调用mapToObj而不仅仅是map, int

This should work as expected:

这应该按预期工作:

String commaSeparatedNumbers = Arrays.stream(numbers)
    .mapToObj(i -> ((Integer) i).toString()) //i is an int, not an Integer
    .collect(Collectors.joining(", "));

which you can also write:

你也可以写:

String commaSeparatedNumbers = Arrays.stream(numbers)
    .mapToObj(Integer::toString)
    .collect(Collectors.joining(", "));

回答by Alexis C.

Arrays.stream(numbers)creates an IntStreamunder the hood and the map operation on an IntStreamrequires an IntUnaryOperator(i.e a function int -> int). The mapping function you want to apply does not respect this contract and hence the compilation error.

Arrays.stream(numbers)IntStream在幕后创建一个,并且对 an 的映射操作IntStream需要一个IntUnaryOperator(即一个函数int -> int)。您要应用的映射函数不遵守此约定,因此会出现编译错误。

You would need to call boxed()before in order to get a Stream<Integer>(this is what Arrays.asList(...).stream()returns). Then just call mapas you did in the first snippet.

您需要在boxed()之前调用才能获得一个Stream<Integer>(这是Arrays.asList(...).stream()返回的内容)。然后就像map你在第一个片段中所做的那样调用。

Note that if you need boxed()followed by mapyou probably want to use mapToObjdirectly.

请注意,如果您需要boxed()跟随,map您可能想mapToObj直接使用。

The advantage is that mapToObjdoesn't require to box each intvalue to an Integerobject; depending on the mapping function you apply of course; so I would go with this option which is also shorter to write.

优点是mapToObj不需要将每个int值装箱到一个Integer对象;当然,这取决于您应用的映射函数;所以我会选择这个写起来也更短的选项。

回答by codebot

You can create an Integer Stream using Arrays.stream(int[]) , you can call mapToObjlike mapToObj(Integer::toString).

您可以使用 Arrays.stream(int[]) 创建一个整数流,您可以调用mapToObjlike mapToObj(Integer::toString)

String csn = Arrays.stream(numbers) // your numbers array
.mapToObj(Integer::toString)
.collect(Collectors.joining(", "));

Hope this helps..

希望这可以帮助..

回答by jamesc1101

If the purpose of this sample and question is to figure out how to map strings to a stream of ints (for example, using a stream of ints to access an index in an Array of strings), you can also use boxing, then casting to an int (which would then allow accessing the index of the array).

如果此示例和问题的目的是弄清楚如何将字符串映射到整数流(例如,使用整数流访问字符串数组中的索引),您还可以使用装箱,然后强制转换为一个 int (然后允许访问数组的索引)。

int[] numbers = {0, 1, 2, 3}; 
String commaSeparatedNumbers = Arrays.stream(numbers)
    .boxed()
    .map((Integer i) -> Integer.toString((int)i))
    .collect(Collectors.joining(", "));

The .boxed() call converts your IntStream (a stream of primitive ints) to a Stream (a stream of objects -- namely, Integer objects) which will then accept the return of an object (in this case, a String object) from your lambda. Here it is just a string representation of the number for demonstration purposes, but it could just as easily (and more practically) be any string object -- like the element of a string array as mentioned before.

.boxed() 调用将您的 IntStream(原始整数流)转换为 Stream(对象流——即 Integer 对象),然后它将接受从你的拉姆达。这里它只是用于演示目的的数字的字符串表示,但它也可以很容易(并且更实际地)是任何字符串对象——就像前面提到的字符串数组的元素一样。

Just thought I'd offer another possibility. In programming, there are always multiple ways of accomplishing a task. Know as many as you can, then choose the one that fits the best for the task at hand, keeping in mind performance issues, intuitiveness, clarity of code, your preferences in coding style, and the most self-documenting.

只是想我会提供另一种可能性。在编程中,总是有多种方法可以完成一项任务。尽可能多地了解,然后选择最适合手头任务的方法,同时牢记性能问题、直观性、代码清晰度、您对编码风格的偏好以及最自我记录的方式。

Happy coding!

快乐编码!

回答by AbuNassar

No boxing, AFAIK, and no explosion of little strings added to the heap:

没有拳击,AFAIK,也没有添加到堆中的小字符串爆炸:

public static void main(String[] args) {
    IntStream stream = IntStream.of(1, 2, 3, 4, 5, 6);
    String s = stream.collect(StringBuilder::new, (builder, n) -> builder.append(',').append(n), (x, y) -> x.append(',').append(y)).substring(1);
    System.out.println(s);
}