假设我们有一个如下列表。 CoreResult
的字段为List<Double>
。
final List<CoreResult> list = new LinkedList<>(SOME_DATA);
目标是在从每个CoreResult
对象中提取特定字段后展平列表。
这里有3种可能的选择。他们中的任何一个都比其他人更好吗?
选项1 :通过map()
提取字段并在收集器内展平
final List<Double> A = list.stream().map(CoreResult::getField)
.collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);
选项2 :通过map()
提取字段,通过flatMap()
展开,简单收集器
final List<Double> B = list.stream().map(CoreResult::getField)
.flatMap(Collection::stream).collect(Collectors.toList());
选项3 :通过flatMap()
,简单的收集器
final List<Double> C = list.stream().flatMap(
x -> x.getField().stream()).collect(Collectors.toList());
如果不需要从CoreResult中提取任何字段,那么答案是否会有所不同,而是想要简单地展平List<List<Double>>
?
答案 0 :(得分:18)
我不确定每个的性能,但java流使用的构建器模式的一个重要方面是它允许可读性。我个人认为选项2是最具可读性的。选项3也很好。我会避免选择一,因为它会“欺骗”收藏品的扁平化。
将每个方法放在自己的行上,并确定哪个方法最直观。我更喜欢第二个:
final List<Double> B = list.stream()
.map(CoreResult::getField)
.flatMap(Collection::stream)
.collect(Collectors.toList());
答案 1 :(得分:7)
我会选择选项2或3.如果你想要展平List<List<Double>>
,你会这样做:
List<Double> list = doubleList.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
答案 2 :(得分:0)
选项3和2是相同的,如果你想首先映射,然后是平面地图或只是平面地图,那么由您决定。
使用选项1,您必须打开另一个流来执行进一步的操作。