Итак, я пытался использовать reduce
, чтобы взять List<String>
и создать Map<String,List<Integer>>
, где ключ карты - элемент оригинала List
, а значение - List
индексов, где этот ключ произошел. Как правило, это очень простая операция в большинстве других языков, использующих Reduce, Inject, Fold и др. c. Например, в Javascript вы могли бы просто сделать это:
let mappings = someStrings.reduce( function( mappings, val, index ) {
if( !mappings[val] ) {
mappings[ val ] = [];
}
mappings[ val ].push( index );
return mappings;
}, {});
Однако то, что я обнаружил, было сократить в Java довольно сложно, потому что 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 );
Если я вынужден фактически объединить x и y, тогда это становится довольно сложным для простого однопоточного случая при объединении вещей, которые являются сложными объектами , Это действительно показывает сложность, созданную из принятого решения Java.
Мой вопрос: я что-то упускаю из-за снижения? Есть ли способ уменьшить (каламбур) параллельный дизайн в однопоточное проектирование, делая его проще, чем я просто не вижу? Опция параллельной работы хороша, но большую часть времени я доволен простым однопоточным сокращением.