Как просто уменьшить коллекцию до объекта, используя Java уменьшить без параллельного багажа? - PullRequest
2 голосов
/ 25 апреля 2020

Итак, я пытался использовать 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.

Мой вопрос: я что-то упускаю из-за снижения? Есть ли способ уменьшить (каламбур) параллельный дизайн в однопоточное проектирование, делая его проще, чем я просто не вижу? Опция параллельной работы хороша, но большую часть времени я доволен простым однопоточным сокращением.

1 Ответ

3 голосов
/ 27 апреля 2020

Ваша операция выглядит сложной по двум причинам. Сначала вы выполняете ненужную промежуточную операцию сопоставления с типом пары. Во-вторых, вы используете не тот инструмент для работы. Вместо Сокращение вам нужно Изменяемое сокращение .

Полная операция может быть записана как

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

См. Также the groupingBy коллектор .

...