我不是Java 8的新手,我知道流是非常强大,便捷的数据处理方式,而且我经常使用它们。实际上,我使用流进行了更多的复杂数据处理,没有任何问题,但是看看吗?看起来很基本的处理,但是类型擦除存在问题。为什么它不能处理这样的数据收集?
Set[] arrOfSets = {new TreeSet<>(List.of(1, 2)), new LinkedHashSet<>(Arrays.asList(1, 2, 3, null))};
/*why type erasure wins here? */
List<Number> collect = (List<Number>) Arrays.stream(arrOfSets).flatMap(Set::Stream).collect(Collectors.toList());
Object collect2 = Arrays.stream(arrOfSets).flatMap(set -> set.stream()).collect(Collectors.toList());
System.out.println("Collect2:" + collect2); /*[1, 2, 1, 2, 3, null]*/
/*Here type interference works fine*/
List<Integer> collect1 = new TreeSet<>(Arrays.asList(1, 2, 3)).stream().collect(Collectors.toList());
System.out.println(collect2.getClass().getSimpleName()); //ArrayList
与List<Set>
相同:
List<?> collect3 = listOfSets.stream().flatMap(Set::stream).collect(Collectors.toList());
运行时异常:java:不兼容的类型:java.lang.Object无法转换为java.util.List
我觉得这是河流的巨大缺点。在将来的sdk中是否有任何机会改善Streams API中的类型干扰,或者没有办法解决该问题?
答案 0 :(得分:1)
问题是您使用的是没有通用类型的原始Set[]
。
要使代码正常工作,您应该使用通用数组:
Set<Number>[] arrOfSets = new Set[]{
new TreeSet<>(List.of(1, 2)),
new LinkedHashSet<>(Arrays.asList(1, 2, 3, null))
};
List<Number> collect = Arrays.stream(arrOfSets) // Stream<Set<Number>>
.flatMap(Set::stream) // Stream<Number>
.collect(Collectors.toList());
或使用Stream<Object>
将流从Stream<Number>
投射到Stream.map()
:
Set[] arrOfSets = new Set[]{
new TreeSet<>(List.of(1, 2)),
new LinkedHashSet<>(Arrays.asList(1, 2, 3, null))
};
List<Number> collect = Arrays.stream(arrOfSets) // Stream<Set>
.map(i -> (Set<Number>) i) // Stream<Set<Number>>
.flatMap(Set::stream) // Stream<Object>
.collect(Collectors.toList());
正如您已经提到的,List<Set>
的问题相同。 Set
没有类型,因此像以前一样使用List<Set<Number>>
或强制类型转换。 我建议使用键入的List
或Set
。