如何使用JavaReduce将一个集合简化为一个对象,而不需要并行行李?

如何使用JavaReduce将一个集合简化为一个对象,而不需要并行行李?,java,java-stream,reduce,Java,Java Stream,Reduce,因此,我尝试使用reduce获取列表,并创建一个Map,其中Map的键是原始列表的成员,该值是该键所在索引的列表。通常,这是一个非常简单的操作,大多数其他语言都使用reduce、inject、fold等。例如,在Javascript中,您可以这样做: let mappings = someStrings.reduce( function( mappings, val, index ) { if( !mappings[val] ) { mappings[ val ] = [

因此,我尝试使用
reduce
获取
列表
,并创建一个
Map
,其中Map的键是原始
列表
的成员,该值是该键所在索引的
列表
。通常,这是一个非常简单的操作,大多数其他语言都使用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认为应该编写函数操作,这样它们就可以“透明地”并行化,但对于这样的简单情况,这会增加额外的开销。在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 );
列表标题=。。。
Map mappings=IntStream.range(0,headers.size())
.map(i->新对(headers.get(i),i))
.reduce(新的HashMap(),(映射,对)->{
如果(!mappings.contains(pair.getFirst())){
mappings.put(pair.getFirst(),new ArrayList());
}
get(pair.getFirst()).add(pair.getSecond());
返回映射;
},(x,y)->x);
如果我被迫实际合并x和y,那么在合并复杂对象时,对于简单的单线程情况,它会变得相当复杂。这确实显示了Java所做的设计决策所带来的复杂性


我的问题是我是否遗漏了一些关于reduce的内容?有没有一种方法可以将并行设计简化为单线程设计,使之更简单,而我却看不到?并行的选项很好,但大多数时候我对简单的单线程reduce很满意。

由于两个原因,您的操作看起来很复杂。首先,您正在执行映射到对类型的不必要的中间操作。其次,你在工作中使用了错误的工具。而不是你需要的

完整的操作可以写成

Map<String,List<Integer>> mappings = IntStream.range(0, headers.size()).boxed()
    .collect(Collectors.groupingBy(headers::get));
Map mappings=IntStream.range(0,headers.size()).boxed()
.collect(collector.groupingBy(headers::get));

另请参见。

Map mappings=IntStream.range(0,headers.size()).boxed().collect(Collectors.groupingBy(header::get))简单,可以并行工作(即使并行运行时不太可能有好处)。这似乎是一个答案,而不是注释。但是谢谢你。你为什么不换个答案呢?所以我做的这个具体操作是一个简单的分组操作。我经常使用可变约化。如果我正在做的不是groupBy操作,我会创建自己的收集器实现来编写其他可变的缩减吗?您可以使用,其中一些是可组合的,例如
groupingBy(func,collectingAndThen(mapping(mapFunc,toList()),finisher))
。您也可以实现自己的收集器,但不需要实现接口,使用三个或四个函数就足够了。有时,调用已经足以定义和使用临时收集器。