Сохранять порядок в потоке Java с помощью команды collect - PullRequest
0 голосов
/ 05 июня 2018

Я столкнулся с небольшой проблемой, когда мне нужно сохранить порядок при выполнении операции над списком строк и с использованием метода collect из API Java-потоков.

public List<String> countOccurrences(ArrayList<String> messages) {
        List<String> stackedMessages = new LinkedList<>();
        HashMap<String, Integer> messageOccurrences = 
                   messages.stream()
                           .collect(groupingBy(Function.identity(), summingInt(e -> 1)));

        messageOccurrences.forEach((key, value) -> {
            String appendString = value == 1 ? "" : " (" + value + " times)";
            stackedMessages.add(key + appendString);
        });

        return stackedMessages;
    }

Проблема с приведенным выше кодом заключается в том, что если я обрабатываю список, такой как ["blah", "blah", "yep"], он возвращает ["yep", "blah (2 times)"], где мне нужно, чтобы он возвратил ["blah (2 times)", "yep"].

Я уже посмотрел этот пост здесь, и меня убедили, что, если я использую поток в уже упорядоченной структуре данных, порядок будет гарантирован: Как обеспечить порядок обработки в потоках java8?

Я думаю, мне нужно изменить groupingBy на toMap, и сейчас я читаю эту документацию.Любой, кто хорошо разбирается в предмете уже, пожалуйста, предложите несколько указателей.

ОБНОВЛЕНИЕ:

Благодаря пользователю @ Aominè, это правильный способ сделать это с помощью groupingBy

.collect(groupingBy(Function.identity(),LinkedHashMap::new, summingInt(e->1)))

1 Ответ

0 голосов
/ 05 июня 2018

Вам нужно будет набрать LinkedHashMap, чтобы получить ожидаемый результат.Кроме того, вам не нужно делать еще один forEach отдельно от конвейера потока после groupingBy, просто создайте поток из entrySet и map, а затем соберите его в список.

return messages.stream()
               .collect(groupingBy(Function.identity(), LinkedHashMap::new, summingInt(e -> 1)))
               .entrySet()
               .stream()
               .map(e -> e.getKey()+(e.getValue() == 1 ? "" : " (" + e.getValue() +" times)"))
               .collect(toList());
...