将原始流收集到类型化集合中?
Collecting a raw stream into a typed collection?
我正在调用 return 原始 Stream
的库方法。我知道流中元素的类型,并希望收集到具有声明的元素类型的集合中。这样做的好处是什么,或者不是那么可怕?
最小可重现示例
为了一个可重现的例子,假设我想调用这个方法:
@SuppressWarnings("rawtypes")
static Stream getStream() {
return Stream.of("Example");
}
我曾希望这会起作用,但我不明白为什么它不起作用:
List<String> stringList = getStream().map(s -> (String) s).collect(Collectors.toList());
我得到 类型不匹配:无法从对象转换为列表。为什么?
解决方法
未经检查的演员表有效。为了缩小需要标记为故意未选中的位,我们可以这样做
@SuppressWarnings("unchecked")
Stream<String> stringStream = getStream();
List<String> stringList = stringStream.collect(Collectors.toList());
在 Java 8 和 Java 11 上,returned 列表是 java.util.ArrayList
,它包含预期的 String
元素。
我的搜索结果与否
我尝试在我的搜索引擎中搜索诸如 java 收集原始流 之类的术语。它并没有给我带来任何帮助。有一个已关闭的 Java 错误(link 在底部)提到一旦你对原始类型进行操作,一切都会变得原始。但是这个完全原始的版本也不起作用:
List stringList = getStream().collect(Collectors.toList());
我仍然收到 类型不匹配:无法从对象转换为列表。怎么会?
我们正在为 Java 8 编码(还有一点时间)。
我知道这个问题有一些基于观点的东西。我仍然希望您能为我提供一些事实,帮助我编写通常被认为更好的代码。
背景:休眠 5
我想调用的方法是 org.hibernate.query.Query.getResultStream()
在原始 Query
上(Query
缺少类型参数)。我想获取流,因为我对要收集到的集合类型有特殊要求。在我的生产代码中,我使用的是 Collectors.toCollection()
(不是本问题示例中的 Collectors.toLlist()
)。顺便说一句,在写这个问题时,我找到了一种方法来说服 Hibernate return 类型化流。我仍然觉得这个问题足够有趣 post。
Link
提示在 Java 错误记录中好吧:一旦我使用原始类型,一切都变得原始。 Stream.collect()
也是一个泛型方法,所以它的原始版本 returns — Object
,不要惊讶。
我调用的Stream
方法声明如下:
<R,A> R collect(Collector<? super T,A,R> collector)
所以它 returns 一个 R
,它可以从通过的收集器收集什么 R
(无论是 Collectors.toList()
还是某些 Collectors.toCollection()
) .一旦一切都变得原始,演绎就不再有效。和 collect()
returns Object
.
总而言之:泛型是好的。当我无法避免得到一些原始的东西时,尽早将它转换成它的通用对应物。
编辑: 感谢 Sweeper 和 Holger 在评论中提供的宝贵意见,这是我的首选解决方案:
Stream<?> wildcardStream = getStream();
List<String> stringList = wildcardStream.map(s -> (String) s)
.collect(Collectors.toList());
System.out.println(stringList.getClass());
System.out.println(stringList);
Java11 上的输出:
class java.util.ArrayList
[Example]
将 Stream
转换为 Stream<?>
(隐式或显式)无需未经检查的操作即可摆脱原始类型。之后 map()
可以按预期使用。而且不需要 @SuppressWarnings("unchecked")
.
这也意味着我最初的 Hibernate 方案的解决方案是在调用 getResultStream()
之前将 Query
对象 转换为 Query<?>
而不仅仅是投射流。然后以与上述相同的方式在流操作中将每个单独的对象转换为map()
。
我正在调用 return 原始 Stream
的库方法。我知道流中元素的类型,并希望收集到具有声明的元素类型的集合中。这样做的好处是什么,或者不是那么可怕?
最小可重现示例
为了一个可重现的例子,假设我想调用这个方法:
@SuppressWarnings("rawtypes")
static Stream getStream() {
return Stream.of("Example");
}
我曾希望这会起作用,但我不明白为什么它不起作用:
List<String> stringList = getStream().map(s -> (String) s).collect(Collectors.toList());
我得到 类型不匹配:无法从对象转换为列表。为什么?
解决方法
未经检查的演员表有效。为了缩小需要标记为故意未选中的位,我们可以这样做
@SuppressWarnings("unchecked")
Stream<String> stringStream = getStream();
List<String> stringList = stringStream.collect(Collectors.toList());
在 Java 8 和 Java 11 上,returned 列表是 java.util.ArrayList
,它包含预期的 String
元素。
我的搜索结果与否
我尝试在我的搜索引擎中搜索诸如 java 收集原始流 之类的术语。它并没有给我带来任何帮助。有一个已关闭的 Java 错误(link 在底部)提到一旦你对原始类型进行操作,一切都会变得原始。但是这个完全原始的版本也不起作用:
List stringList = getStream().collect(Collectors.toList());
我仍然收到 类型不匹配:无法从对象转换为列表。怎么会?
我们正在为 Java 8 编码(还有一点时间)。
我知道这个问题有一些基于观点的东西。我仍然希望您能为我提供一些事实,帮助我编写通常被认为更好的代码。
背景:休眠 5
我想调用的方法是 org.hibernate.query.Query.getResultStream()
在原始 Query
上(Query
缺少类型参数)。我想获取流,因为我对要收集到的集合类型有特殊要求。在我的生产代码中,我使用的是 Collectors.toCollection()
(不是本问题示例中的 Collectors.toLlist()
)。顺便说一句,在写这个问题时,我找到了一种方法来说服 Hibernate return 类型化流。我仍然觉得这个问题足够有趣 post。
Link
提示在 Java 错误记录中好吧:一旦我使用原始类型,一切都变得原始。 Stream.collect()
也是一个泛型方法,所以它的原始版本 returns — Object
,不要惊讶。
我调用的Stream
方法声明如下:
<R,A> R collect(Collector<? super T,A,R> collector)
所以它 returns 一个 R
,它可以从通过的收集器收集什么 R
(无论是 Collectors.toList()
还是某些 Collectors.toCollection()
) .一旦一切都变得原始,演绎就不再有效。和 collect()
returns Object
.
总而言之:泛型是好的。当我无法避免得到一些原始的东西时,尽早将它转换成它的通用对应物。
编辑: 感谢 Sweeper 和 Holger 在评论中提供的宝贵意见,这是我的首选解决方案:
Stream<?> wildcardStream = getStream();
List<String> stringList = wildcardStream.map(s -> (String) s)
.collect(Collectors.toList());
System.out.println(stringList.getClass());
System.out.println(stringList);
Java11 上的输出:
class java.util.ArrayList [Example]
将 Stream
转换为 Stream<?>
(隐式或显式)无需未经检查的操作即可摆脱原始类型。之后 map()
可以按预期使用。而且不需要 @SuppressWarnings("unchecked")
.
这也意味着我最初的 Hibernate 方案的解决方案是在调用 getResultStream()
之前将 Query
对象 转换为 Query<?>
而不仅仅是投射流。然后以与上述相同的方式在流操作中将每个单独的对象转换为map()
。