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

时间:2015-03-13 09:39:40

标签: java functional-programming java-8 java-stream

此代码有效(在Javadoc中使用):

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

这个不能编译:

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

IDEA告诉我,我在lambda表达式&#34;中有一个&#34;不兼容的返回类型字符串。

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

5 个答案:

答案 0 :(得分:102)

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

这应该按预期工作:

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

你也可以写:

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

答案 1 :(得分:19)

Arrays.stream(numbers)在底层创建IntStreamIntStream上的地图操作需要IntUnaryOperator(即函数int -> int)。您要应用的映射函数不遵守此契约,因此也不符合编译错误。

您需要先调用boxed()才能获得Stream<Integer>(这是Arrays.asList(...).stream()返回的内容)。然后像在第一个代码段中那样拨打map

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

优点是mapToObj不需要将每个int值封装到Integer个对象;取决于你当然适用的映射功能;所以我会选择这个也更短的选项。

答案 2 :(得分:4)

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

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

希望这会有所帮助..

答案 3 :(得分:1)

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

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

.boxed()调用将IntStream(原始int的流)转换为Stream(对象流 - 即Integer对象),然后接受对象的返回(在本例中为String)来自你的lambda。这里只是用于演示目的的数字的字符串表示,但它可以很容易(并且更实际地)是任何字符串对象 - 如前面提到的字符串数组的元素。

以为我会提供另一种可能性。在编程中,总有多种方法可以完成任务。尽可能多地了解,然后选择最适合手头任务的那个,记住性能问题,直观性,代码清晰度,编码风格偏好以及最自我记录。

快乐的编码!

答案 4 :(得分:0)

没有拳击,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);
}