【发布时间】:2019-06-03 09:58:56
【问题描述】:
简介
我确实对 jdk11(及更高版本)在流和收集方法方面的行为有疑问。
我确实想获取流式传输资源的参数化容器的值,并最终使用.collect(Collectors.toSet()) 收集这些值。
问题描述
当我用jdk8 编译我的代码时,它工作得非常好。但是由于我们还必须支持jdk11,所以我运行了编译,但它失败了,因为Error:(136, 17) java: incompatible types: java.lang.Object cannot be converted to java.util.Set<org.bson.types.ObjectId>(同样适用于openJdk11)
用例
想象以下情况。我有一个基本上是数据容器的类。此容器可以保存单个值或值列表。
我的应用程序的某些部分,我确实有这个容器类的列表(它也可以包含作为值的列表),我确实想通过列表流式传输以获取容器中的所有值作为平面列表。
对于这个例子,我选择使用 objectIds 列表。
设置
// preparation
List<ObjectId> innerObjects = new ArrayList<>();
innerObjects.add(new ObjectId());
innerObjects.add(new ObjectId());
List<Diamond<Object>> diamonds = new ArrayList<>();
diamonds.add(new Diamond<Object>().value(innerObjects));
容器类
public static class Diamond<T> {
private T value;
public Diamond<T> value(T value) {
this.value = value;
return this;
}
public T getValue() {
return this.value;
}
}
从容器中收集objectId值的实现。这适用于 jdk8 的编译器。但是 jdk11 在这里失败了。
Set<ObjectId> objectIdSet = diamonds
.stream()
.filter(diamond -> diamond.getValue() instanceof List)
.map(Diamond::getValue)
.map(List.class::cast)
.flatMap(Collection::stream)
.map(ObjectId.class::cast)
.collect(Collectors.toSet());
把它改成这个实现会让 jdk11 编译器很开心。
Stream<ObjectId> idStream = diamonds
.stream()
.filter(diamond -> diamond.getValue() instanceof List)
.map(Diamond::getValue)
.map(List.class::cast)
.flatMap(Collection::stream)
.map(ObjectId.class::cast);
Set<ObjectId> objectIds = idStream.collect(Collectors.toSet());
问题
但我不明白为什么这是错误的。
<deleted as of to be inacurate>
编辑: 我更改了设置代码以更多地反映我当前的问题。
有人知道我做错了什么吗?
【问题讨论】:
-
我不明白你的最后一段。你说在你的真实代码中你使用
Diamond<Object>,但你在这里使用了不同的类型。 两种这两种情况是否会引发该异常,还是只有您的Diamond<Object>版本失败? -
我不知道您的问题的答案,但也许您应该考虑始终持有一组值 (
ObjectIds)。是的,可能大部分集合都是Collections.singletonList(value),但这很好。单个项目的集合仍然是一个很好的集合。 -
@GiacomoAlzetta 是的,我的真实代码使用
Diamond<Object>。我尝试了更明确的一个,但都失败了。我会调整我的问题更准确。 -
虽然我没能重现 Java-12 中的编译器问题,但我很好奇你为什么倾向于使用
List<Diamond<Object>> diamonds = new ArrayList<>(); diamonds.add(new Diamond<Object>().value(innerObjects));?
标签: java java-stream collectors