我正在学习如何在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;
}
任何改进或指示都将不胜感激。
答案 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.*;
对于后一种解决方案。