如何在没有并行行李的情况下使用 Java reduce 简单地将集合缩减为对象?
How to simply reduce a collection to an object using Java reduce without the parallel baggage?
所以我尝试使用 reduce
获取 List<String>
并创建一个 Map<String,List<Integer>>
,其中地图的键是原始 List
的成员,并且该值是出现该键的索引的 List
。一般来说,这是一个非常简单的操作,大多数其他语言使用 reduce、inject、fold 等。例如在 Javascript 中你可以这样做:
let mappings = someStrings.reduce( function( mappings, val, index ) {
if( !mappings[val] ) {
mappings[ val ] = [];
}
mappings[ val ].push( index );
return mappings;
}, {});
然而,我发现 Java 中的 reduce 相当复杂,因为 Java 认为应该编写函数式操作,以便它们可以 "transparently" 并行化,但这增加了像这样的简单情况的额外开销。在Java中不得不写点比较蛋疼的东西:
List<String> headers = ...
Map<String,List<Integer>> mappings = IntStream.range(0, headers.size())
.map( i -> new Pair<String,Integer>( headers.get(i), i ) )
.reduce( new HashMap<>(), ( mapping, pair ) -> {
if( !mappings.contains( pair.getFirst() ) ) {
mappings.put( pair.getFirst(), new ArrayList<String>() );
}
mappings.get( pair.getFirst() ).add( pair.getSecond() );
return mappings;
}, ( x, y ) -> x );
如果我被迫实际合并 x 和 y,那么在合并复杂对象时对于简单的单线程情况会变得相当复杂。这确实显示了 Java 做出的设计决策所带来的复杂性。
我的问题是我是否遗漏了一些关于 reduce 的信息?有没有一种方法可以将并行设计减少(双关语)为单线程设计,从而使我看不到的更简单?并行选项很好,但大多数时候我对简单的单线程 reduce 感到满意。
您的操作看起来很复杂,原因有二。首先,您正在执行映射到对类型的不必要的中间操作。其次,您在工作中使用了错误的工具。而不是 Reduction you need Mutable Reduction.
完整的操作可以写成
Map<String,List<Integer>> mappings = IntStream.range(0, headers.size()).boxed()
.collect(Collectors.groupingBy(headers::get));
所以我尝试使用 reduce
获取 List<String>
并创建一个 Map<String,List<Integer>>
,其中地图的键是原始 List
的成员,并且该值是出现该键的索引的 List
。一般来说,这是一个非常简单的操作,大多数其他语言使用 reduce、inject、fold 等。例如在 Javascript 中你可以这样做:
let mappings = someStrings.reduce( function( mappings, val, index ) {
if( !mappings[val] ) {
mappings[ val ] = [];
}
mappings[ val ].push( index );
return mappings;
}, {});
然而,我发现 Java 中的 reduce 相当复杂,因为 Java 认为应该编写函数式操作,以便它们可以 "transparently" 并行化,但这增加了像这样的简单情况的额外开销。在Java中不得不写点比较蛋疼的东西:
List<String> headers = ...
Map<String,List<Integer>> mappings = IntStream.range(0, headers.size())
.map( i -> new Pair<String,Integer>( headers.get(i), i ) )
.reduce( new HashMap<>(), ( mapping, pair ) -> {
if( !mappings.contains( pair.getFirst() ) ) {
mappings.put( pair.getFirst(), new ArrayList<String>() );
}
mappings.get( pair.getFirst() ).add( pair.getSecond() );
return mappings;
}, ( x, y ) -> x );
如果我被迫实际合并 x 和 y,那么在合并复杂对象时对于简单的单线程情况会变得相当复杂。这确实显示了 Java 做出的设计决策所带来的复杂性。
我的问题是我是否遗漏了一些关于 reduce 的信息?有没有一种方法可以将并行设计减少(双关语)为单线程设计,从而使我看不到的更简单?并行选项很好,但大多数时候我对简单的单线程 reduce 感到满意。
您的操作看起来很复杂,原因有二。首先,您正在执行映射到对类型的不必要的中间操作。其次,您在工作中使用了错误的工具。而不是 Reduction you need Mutable Reduction.
完整的操作可以写成
Map<String,List<Integer>> mappings = IntStream.range(0, headers.size()).boxed()
.collect(Collectors.groupingBy(headers::get));