Каков наилучший способ реализовать функцию счетчика Python в Java? - PullRequest
0 голосов
/ 05 июня 2018

Я изучаю, как использовать потоки в Java, и я хотел бы знать наиболее эффективный способ скопировать функциональность счетчика Python в Java.

Для тех, кто не знаком с подсчетом Python, см. здесь .

Я уже сделал наивную реализацию, но сомневаюсь, что это когда-либо будет добавлено в среду производственного уровня:

private List<String> countMessages(List<String> messages) {
        Map<String, Integer> messageOccurrences = new HashMap<>();
        List<String> stackedMessages = new LinkedList<String>();
        this.messages.stream().filter((message) -> (messageOccurrences.containsKey(message))).forEachOrdered((message) -> {
                    int new_occ = messageOccurrences.get(message) + 1;
                    messageOccurrences.put(message, new_occ);
        });
        messageOccurrences.keySet().forEach((key) -> {
            stackedMessages.add(key + "(" + messageOccurrences.get(key) + "times)" );
        });
        return stackedMessages;
    }

Любые улучшения или указатели будут оценены.

1 Ответ

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

Чтобы ответить на вопрос «каков наилучший способ реализовать функцию подсчета Python в Java?».

У Java уже есть Collections.frequency , который будет делать именно это.

Однако, если вы хотите сделать это с помощью API потоков, то я считаю, что общее решение будет:

public static <T> long count(Collection<T> source, T element) {
       return source.stream().filter(e -> Objects.equals(e, element)).count();
}

тогда вариант использования будет:

long countHellp = count(myStringList, "hello");
long countJohn = count(peopleList, new Person("John"));
long count101 = count(integerList, 101); 
...
...

, или вы даже можете передать предикат, если хотите:

public static <T> long count(Collection<T> source, Predicate<? super T> predicate) {
       return source.stream().filter(predicate).count();
}

Тогда вариант использованиянапример:

long stringsGreaterThanTen = count(myStringList, s -> s.length() > 10);
long malesCount = count(peopleList, Person::isMale);
long evens = count(integerList, i -> i % 2 == 0); 
...
...

Учитывая ваш комментарий к сообщению, похоже, что вы хотите "сгруппировать" и получить количество каждой группы.

public Map<String, Long> countMessages(List<String> messages) {
        return messages.stream()
                       .collect(groupingBy(Function.identity(), counting()));
}

Это создает поток из списка messages и затем группирует их, передавая counting() в качестве нижестоящего сборщика, что означает, что мы получим Map<String, Long>, где ключи - это элементы, а значения - вхождения этой конкретной строки.

Убедитесь, что у вас есть импорт:

import static java.util.stream.Collectors.*;

для последнего решения.

...