如何查找最频繁的元素,但是当最频繁的元素很少时,返回null。
我想找到与以下代码等效的代码:
public static void main(String[] args) {
System.out.println("Should return A -> " + mostFrequent(Arrays.asList("A", "A", "B")));
System.out.println("Should null as element in list have same frequency -> "
+ mostFrequent(Arrays.asList("A", "B")));
}
private static String mostFrequent(List<String> elements) {
Map<String, Long> ordered = new TreeMap<>();
for (String e : elements) {
if (!ordered.containsKey(e)) {
ordered.put(e, 0L);
}
Long tmp = ordered.get(e);
ordered.put(e, ++tmp);
}
String mostFrequent = null;
long i = 0;
Iterator<Map.Entry<String, Long>> it = ordered.entrySet().iterator();
while (it.hasNext() && i < 2) {
Map.Entry<String, Long> pair = it.next();
if (i == 0) {
mostFrequent = pair.getKey();
} else {
if (ordered.get(mostFrequent) == ordered.get(pair.getKey())) {
return null;
}
}
i++;
}
return mostFrequent;
}
但是,流版本不能处理具有相同频率的最常见元素。
private static String mostFrequentStream(List<String> elements) {
return elements.stream()
.reduce(BinaryOperator.maxBy(
Comparator.comparingInt(o -> Collections.frequency(elements, o))))
.orElse(null);
}
如何通过修改上面的流来实现它?
答案 0 :(得分:3)
使用分组依据:
String mostFrequentStream(List<String> elements) {
Map<String, Long> temp = elements.stream()
.collect(Collectors.groupingBy(a -> a, Collectors.counting()));
return new HashSet<>(temp.values()).size() < temp.size() ?
null : temp.entrySet()
.stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey).get();
}
答案 1 :(得分:2)
我设法构建了一个串联的Stream
,但时间很长:
private static String mostFrequentStream3(List<String> elements) {
return elements.stream() // part 1
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream() // part 2
.collect(Collectors.groupingBy(Entry::getValue))
.entrySet().stream() // part 3
.max(Entry.comparingByKey())
.map(Entry::getValue)
.filter(v -> v.size() == 1)
.map(v -> v.get(0).getKey())
.orElse(null);
}
要“查找最频繁的元素,但是当最频繁的元素很少时,返回null”
第1部分计算了每个元素的频率。
第2部分按频率对条目进行分组。
第3部分查找频率最高的条目。如果该条目仅包含一个元素(“最常出现的很少”),则它是一个且唯一的最大值。否则返回null
。
答案 2 :(得分:0)
我永远不会使用流来避免同时损害可读性和性能。为了好玩-
private static String mostFrequentStream(List<String> elements) {
Map<String, Long> frequencyMap = elements.stream().collect(groupingBy(Function.identity(), counting()));
return frequencyMap.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.limit(2).reduce((i, e) -> i.getValue().equals(e.getValue()) ? new AbstractMap.SimpleEntry<>(null, 0L) : i).get().getKey();
}