在java中实现python count函数的最佳方法是什么?

时间:2018-06-04 21:48:23

标签: java functional-programming java-stream

我正在学习如何在java中使用流,我想知道将python计数功能复制到java中的最有效方法。

对于那些不熟悉python计数的人,请参阅here

我已经做了一个天真的实现,但我怀疑这会被添加到生产级环境中:

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 :(得分:4)

回答“在java中实现python count函数的最佳方法是什么?”。

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.*;

对于后一种解决方案。