使用 Java Stream 将一串数字解析为 Integer 对象的 List
Use Java Stream to parse a string of digits as a List of Integer objects
我的问题受到 的启发,但旨在使用 Java 流到达 List<Integer>
.
我有这样的代码。它似乎正在返回一个 ArrayList
,大概是 ArrayList<Integer>
。但是编译器拒绝让我这样声明结果。
String input = "1 2 3 4 5";
Stream stream = Arrays.stream( input.split( " " ) );
var x = stream.map( s -> Integer.valueOf( ( String ) s ) ).collect( Collectors.toList() );
这在使用最新 Java 版本的新 var
功能时运行。
System.out.println( x.getClass() );
System.out.println( x );
class java.util.ArrayList
[1, 2, 3, 4, 5]
我有两个问题:
- 为什么
x
报为ArrayList
,而我却不能声明x
为ArrayList(错误:类型不兼容),如:
ArrayList<Integer> x = stream.map( s -> Integer.valueOf( ( String ) s ) ).collect( Collectors.toList() );
- 是否有更好的方法使用流将这串数字转换为
Integer
的List
?
List<Integer> list = Arrays.stream("1 2 3 4 5".split(" ")).map(s -> Integer.valueOf(s)).collect(Collectors.toList());
编译通过。根据 collectors source code:“类型、可变性无法保证,
* 返回的 {@code List} 的可序列化性或线程安全性;“
首先,您的 Stream
是原始的。使用原始类型意味着任何使用类型参数的内容都将被擦除到其上限,此处 Object
。所以 map
return 是另一个原始 Stream
和 collect
return 是 Object
。轻松修复:Stream<String>
.
Stream<String> stream = Arrays.stream( input.split( " " ) );
其次,Collectors.toList
指定为returnList<T>
,或者List<String>
这里
There are no guarantees on the type, mutability, serializability, or thread-safety of the List
returned; if more control over the returned List
is required, use toCollection(Supplier)
.
如果您对 List
不满意并且您绝对需要一个 ArrayList
,请提供一个:
.collect(Collectors.toCollection(ArrayList::new));
顺便说一句,您可以替换 lambda 表达式
s -> Integer.valueOf( ( String ) s )
方法参考
Integer::valueOf
进行这些更改后,您的代码可能如下所示:
String input = "1 2 3 4 5";
Stream< String > stream = Arrays.stream( input.split( " " ) );
List< Integer > x = stream.map( Integer::valueOf ).collect( Collectors.toList() );
或者,如果您坚持 ArrayList
而不是 List
,则:
String input = "1 2 3 4 5";
Stream< String > stream = Arrays.stream( input.split( " " ) );
ArrayList< Integer > x = stream.map( Integer::valueOf ).collect( Collectors.toCollection( ArrayList::new ) );
完成这些更改后,这似乎是将包含 space 分隔的整数的字符串转换为 ArrayList<Integer>
的一种相当好的方法。一个小的改进是将 split
正则表达式参数更改为 "\s+"
,以表示一个或多个白色 space 字符。如果 "1 2"
到达,数字之间有多个 space,这将防止在 space 个字符之间匹配的空字符串。
您可以创建 ArrayList
,但您不应该:
ArrayList<Integer> x =
stream.map(Integer::valueOf)
.collect(Collectors.toCollection(ArrayList::new));
重构:
List<Integer> x =
Arrays.stream(input.split(" "))
.map(Integer::valueOf)
.collect(Collectors.toList());
或者,使用 Pattern.splitAsStream
:
List<Integer> x =
Pattern.compile(" ").splitAsStream("1 2 3 4 5")
.map(Integer::valueOf)
.collect(Collectors.toList());
Why is x reported as an ArrayList yet I cannot declare x to be an ArrayList.
因为
collect(...)
返回静态推断类型,基于 Collectors.toList()
结果的类型。
- 即(在这种情况下)
Collector<String,?,List<String>>
... 根据 Collectors
javadoc。
实际对象是 ArrayList
这一事实是一个实现细节,可以想象在 Java 的未来版本中会发生变化。
Is there a better way to use streams to convert this string of digits to a List of Integer?
我会留给其他人说。但是,我认为更简单/更清晰的方法是不使用流来完成此任务。
String input = "1 2 3 4 5";
var x = new ArrayList<>(Arrays.asList(input.split(" ")));
上面的代码比我见过的基于流的版本更简单,而且很可能更高效。
我的问题受到 List<Integer>
.
我有这样的代码。它似乎正在返回一个 ArrayList
,大概是 ArrayList<Integer>
。但是编译器拒绝让我这样声明结果。
String input = "1 2 3 4 5";
Stream stream = Arrays.stream( input.split( " " ) );
var x = stream.map( s -> Integer.valueOf( ( String ) s ) ).collect( Collectors.toList() );
这在使用最新 Java 版本的新 var
功能时运行。
System.out.println( x.getClass() );
System.out.println( x );
class java.util.ArrayList
[1, 2, 3, 4, 5]
我有两个问题:
- 为什么
x
报为ArrayList
,而我却不能声明x
为ArrayList(错误:类型不兼容),如:ArrayList<Integer> x = stream.map( s -> Integer.valueOf( ( String ) s ) ).collect( Collectors.toList() );
- 是否有更好的方法使用流将这串数字转换为
Integer
的List
?
List<Integer> list = Arrays.stream("1 2 3 4 5".split(" ")).map(s -> Integer.valueOf(s)).collect(Collectors.toList());
编译通过。根据 collectors source code:“类型、可变性无法保证, * 返回的 {@code List} 的可序列化性或线程安全性;“
首先,您的 Stream
是原始的。使用原始类型意味着任何使用类型参数的内容都将被擦除到其上限,此处 Object
。所以 map
return 是另一个原始 Stream
和 collect
return 是 Object
。轻松修复:Stream<String>
.
Stream<String> stream = Arrays.stream( input.split( " " ) );
其次,Collectors.toList
指定为returnList<T>
,或者List<String>
这里
There are no guarantees on the type, mutability, serializability, or thread-safety of the
List
returned; if more control over the returnedList
is required, usetoCollection(Supplier)
.
如果您对 List
不满意并且您绝对需要一个 ArrayList
,请提供一个:
.collect(Collectors.toCollection(ArrayList::new));
顺便说一句,您可以替换 lambda 表达式
s -> Integer.valueOf( ( String ) s )
方法参考
Integer::valueOf
进行这些更改后,您的代码可能如下所示:
String input = "1 2 3 4 5";
Stream< String > stream = Arrays.stream( input.split( " " ) );
List< Integer > x = stream.map( Integer::valueOf ).collect( Collectors.toList() );
或者,如果您坚持 ArrayList
而不是 List
,则:
String input = "1 2 3 4 5";
Stream< String > stream = Arrays.stream( input.split( " " ) );
ArrayList< Integer > x = stream.map( Integer::valueOf ).collect( Collectors.toCollection( ArrayList::new ) );
完成这些更改后,这似乎是将包含 space 分隔的整数的字符串转换为 ArrayList<Integer>
的一种相当好的方法。一个小的改进是将 split
正则表达式参数更改为 "\s+"
,以表示一个或多个白色 space 字符。如果 "1 2"
到达,数字之间有多个 space,这将防止在 space 个字符之间匹配的空字符串。
您可以创建 ArrayList
,但您不应该:
ArrayList<Integer> x =
stream.map(Integer::valueOf)
.collect(Collectors.toCollection(ArrayList::new));
重构:
List<Integer> x =
Arrays.stream(input.split(" "))
.map(Integer::valueOf)
.collect(Collectors.toList());
或者,使用 Pattern.splitAsStream
:
List<Integer> x =
Pattern.compile(" ").splitAsStream("1 2 3 4 5")
.map(Integer::valueOf)
.collect(Collectors.toList());
Why is x reported as an ArrayList yet I cannot declare x to be an ArrayList.
因为
collect(...)
返回静态推断类型,基于Collectors.toList()
结果的类型。- 即(在这种情况下)
Collector<String,?,List<String>>
... 根据Collectors
javadoc。
实际对象是 ArrayList
这一事实是一个实现细节,可以想象在 Java 的未来版本中会发生变化。
Is there a better way to use streams to convert this string of digits to a List of Integer?
我会留给其他人说。但是,我认为更简单/更清晰的方法是不使用流来完成此任务。
String input = "1 2 3 4 5";
var x = new ArrayList<>(Arrays.asList(input.split(" ")));
上面的代码比我见过的基于流的版本更简单,而且很可能更高效。