为什么在从数组流式传输时不能将整数映射到字符串?
Why can't I map integers to strings when streaming from an array?
此代码有效(取自 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 告诉我我有一个 "incompatible return type String in lambda expression".
为什么?以及如何解决这个问题?
Arrays.stream(int[])
创建一个 IntStream
,而不是 Stream<Integer>
。因此,在将 int
映射到对象时,您需要调用 mapToObj
而不仅仅是 map
。
这应该按预期工作:
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(", "));
Arrays.stream(numbers)
在幕后创建了一个 IntStream
,IntStream
上的映射操作需要一个 IntUnaryOperator
(即函数 int -> int
)。您要应用的映射函数不遵守此合同,因此会出现编译错误。
您需要先调用 boxed()
才能获得 Stream<Integer>
(这就是 Arrays.asList(...).stream()
returns)。然后像在第一个片段中那样调用 map
。
请注意,如果您需要 boxed()
后跟 map
,您可能想直接使用 mapToObj
。
优点是 mapToObj
不需要将每个 int
值装箱到一个 Integer
对象;当然取决于您应用的映射功能;所以我会选择这个写起来也更短的选项。
您可以使用 Arrays.stream(int[]) 创建一个整数流,您可以像 mapToObj(Integer::toString)
.
一样调用 mapToObj
String csn = Arrays.stream(numbers) // your numbers array
.mapToObj(Integer::toString)
.collect(Collectors.joining(", "));
希望这对您有所帮助..
如果此示例和问题的目的是弄清楚如何将字符串映射到整数流(例如,使用整数流访问字符串数组中的索引),您还可以使用装箱,然后转换为 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(原始整数流)转换为 Stream(对象流——即 Integer 对象),后者将接受对象的 return(在这种情况下,一个 String 对象)来自你的 lambda。这里它只是用于演示目的的数字的字符串表示形式,但它可以很容易地(并且更实际地)是任何字符串对象——就像前面提到的字符串数组的元素一样。
只是想我会提供另一种可能性。在编程中,总是有多种方法来完成一项任务。尽可能多地了解,然后选择最适合手头任务的那个,同时牢记性能问题、直观性、代码清晰度、您对编码风格的偏好以及最多的自我记录。
编码愉快!
没有装箱,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);
}
除 :: 运算符外:
String numString = numbers.stream()
.map(String::valueOf)
.collect(Collectors.joining(", "));
这在较新的 Java-Versions 中可能很重要。
此代码有效(取自 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 告诉我我有一个 "incompatible return type String in lambda expression".
为什么?以及如何解决这个问题?
Arrays.stream(int[])
创建一个 IntStream
,而不是 Stream<Integer>
。因此,在将 int
映射到对象时,您需要调用 mapToObj
而不仅仅是 map
。
这应该按预期工作:
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(", "));
Arrays.stream(numbers)
在幕后创建了一个 IntStream
,IntStream
上的映射操作需要一个 IntUnaryOperator
(即函数 int -> int
)。您要应用的映射函数不遵守此合同,因此会出现编译错误。
您需要先调用 boxed()
才能获得 Stream<Integer>
(这就是 Arrays.asList(...).stream()
returns)。然后像在第一个片段中那样调用 map
。
请注意,如果您需要 boxed()
后跟 map
,您可能想直接使用 mapToObj
。
优点是 mapToObj
不需要将每个 int
值装箱到一个 Integer
对象;当然取决于您应用的映射功能;所以我会选择这个写起来也更短的选项。
您可以使用 Arrays.stream(int[]) 创建一个整数流,您可以像 mapToObj(Integer::toString)
.
mapToObj
String csn = Arrays.stream(numbers) // your numbers array
.mapToObj(Integer::toString)
.collect(Collectors.joining(", "));
希望这对您有所帮助..
如果此示例和问题的目的是弄清楚如何将字符串映射到整数流(例如,使用整数流访问字符串数组中的索引),您还可以使用装箱,然后转换为 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(原始整数流)转换为 Stream(对象流——即 Integer 对象),后者将接受对象的 return(在这种情况下,一个 String 对象)来自你的 lambda。这里它只是用于演示目的的数字的字符串表示形式,但它可以很容易地(并且更实际地)是任何字符串对象——就像前面提到的字符串数组的元素一样。
只是想我会提供另一种可能性。在编程中,总是有多种方法来完成一项任务。尽可能多地了解,然后选择最适合手头任务的那个,同时牢记性能问题、直观性、代码清晰度、您对编码风格的偏好以及最多的自我记录。
编码愉快!
没有装箱,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);
}
除 :: 运算符外:
String numString = numbers.stream()
.map(String::valueOf)
.collect(Collectors.joining(", "));
这在较新的 Java-Versions 中可能很重要。