使用Collections.frequency()打印某些值
我有一个数组如下:
int[] array = {11, 14, 17, 11, 48, 33, 29, 11, 17, 22, 11, 48, 18};
我想要做的是找到重复的值,并打印出来。
所以我这样做的方法是转换为ArrayList
,然后Set
并使用Set
上的stream
。
ArrayList list = new ArrayList(array.length); for (int i = 0; i < array.length; i++) { list.add(array[i]); } Set dup = new HashSet(list);
然后我使用stream
循环遍历它并使用Collections.frequency
打印值。
dup.stream().forEach((key) -> { System.out.println(key + ": " + Collections.frequency(list, key)); });
当然,即使计数为1,也会将它们全部打印出来。
我想加入if(key > 1)
但它是我想要的值而不是键。
如何在此实例中获取值以仅在value > 2
打印。
我可能会投入:
int check = Collections.frequency(list, key); if (check > 1) {
但是这会在stream
复制Collections.frequency(list, key)
并且非常难看 。
也许你可以使用filter
来获得大于2的值:
dup.stream() .filter(t -> Collections.frequency(list, t) > 2) .forEach(key -> System.out.println(key + ": " + Collections.frequency(list, key)));
结果你的情况是:
11: 4
编辑
另一种方案:
您无需使用Set
或Collections.frequency
即可使用:
Integer[] array = {11, 14, 17, 11, 48, 33, 29, 11, 17, 22, 11, 48, 18}; Arrays.stream(array).collect(Collectors.groupingBy(p -> p, Collectors.counting())) .entrySet().stream().filter(t -> t.getValue() > 1) .forEach(key -> System.out.println(key.getKey() + ": " + key.getValue()));
产量
48: 2 17: 2 11: 4
完整示例没有在循环中初始化dup
并且为每个唯一元素调用Collections.frequency
一次:
Integer[] array = {11, 14, 17, 11, 48, 33, 29, 11, 17, 22, 11, 48, 18}; List list = Arrays.asList(array); Arrays.stream(array).collect(Collectors.toSet()) .stream() .map(v -> new SimpleEntry<>(v, Collections.frequency(list, v))) .filter(v -> v.getValue() > 1) .forEach(v -> System.out.println(v.getKey() + ":" + v.getValue()));
package various; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Set; public class Frequency { public static void main(String[] args) { int[] array = {11, 14, 17, 11, 48, 33, 29, 11, 17, 22, 11, 48, 18}; ArrayList list = new ArrayList<>(array.length); for (int i = 0; i < array.length; i++) { list.add(array[i]); } Set dup = new HashSet<>(list); dup.stream().forEach((key) -> { System.out.print((Collections.frequency(list, key) > 2) ? key + ": " + Collections.frequency(list, key) +"\n" : ""); }); } }
输出:
11: 4
HashMap hashmap = new HashMap<>(); for (int i : array) { if (hashmap.containsKey(i)) { hashmap.put(i, hashmap.get(i) + 1); } else { hashmap.put(i, 1); } }
存储值及其频率。
{48=2, 17=2, 33=1, 18=1, 22=1, 11=4, 29=1, 14=1}
编辑:如果你想打印重复项;
hashmap.entrySet().stream().filter((entry) -> ((int) entry.getValue() >= 2)).forEach((entry) -> { System.out.println(entry.getKey() + ":" + entry.getValue()); });
给你:
48:2 17:2 11:4
这应该工作:
int[] array = {11, 14, 17, 11, 48, 33, 29, 11, 17, 22, 11, 48, 18}; List list = Arrays.stream(array).boxed().collect(Collectors.toList()); // print values appearing more than once list.stream().filter(i -> Collections.frequency(list, i) >1) .collect(Collectors.toSet()).forEach(System.out::println);
会打印:
48 17 11
如果您也希望得到这样的事情,您可以这样做:
int[] array = {11, 14, 17, 11, 48, 33, 29, 11, 17, 22, 11, 48, 18}; List list = Arrays.stream(array).boxed().collect(Collectors.toList()); list.stream() .filter(i -> Collections.frequency(list, i) >1) .collect(Collectors.toMap(identity(), v -> 1, Integer::sum)) .forEach((x, y) -> System.out.println("Key: " + x +", occurence: "+ y));
打印
Key: 48, occurence: 2 Key: 17, occurence: 2 Key: 11, occurence: 4
为了实现所需的function,我们可以促进Java Streams,特别是Stream.collect
方法 :
R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)
请考虑以下草案实施:
import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; import java.util.stream.Collectors; public class Program { public static void main(final String[] args) { // Input. final int[] inputArray = {11, 14, 17, 11, 48, 33, 29, 11, 17, 22, 11, 48, 18}; // Processing. final DuplicateCounter duplicateCounter = Arrays.stream(inputArray) .collect( DuplicateCounter ::new, DuplicateCounter ::accept, DuplicateCounter ::combine ); // Output. System.out.println(duplicateCounter.getDuplicateCountMap()); } private static final class DuplicateCounter implements Consumer { private final Map countMap = new HashMap<>(); public void accept(final T obj) { this.incrementCounter(obj, 1); } public void combine(final DuplicateCounter other) { other.countMap.entrySet() .forEach(entry -> this.incrementCounter(entry.getKey(), entry.getValue())); } public Map getDuplicateCountMap() { return this.countMap.entrySet() .stream() .filter(entry -> entry.getValue() > 1) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } private void incrementCounter(final T obj, int increment) { final Integer counter = this.countMap.getOrDefault(obj, 0); this.countMap.put(obj, counter + increment); } } }
它输出:
{48 = 2,17 = 2,11 = 4}
其他参考:
- 减少(Java™教程>集合>聚合操作) 。
- Java 8 Streams – 收集与减少 。
而另一种function方式:
HashMap result = Arrays.stream(array) .boxed() .collect(Collectors.collectingAndThen(Collectors.groupingBy( Function.identity(), HashMap::new, Collectors.counting()), map -> { map.entrySet().removeIf(x -> x.getValue() == 1); return map; }));
顺便说一句接受的答案 – 这可能是最糟糕的,就像每个元素使用Collections.frequency
每一个建议(即使是唯一的)
Collections.frequency
的问题是它必须遍历所有集合才能找到给定元素的频率。 如果对集合的每个元素执行此操作,那么您的解决方案是O(n^2)
,即非常低效,因为处理时间随着集合中元素数量的平方而增加。
相反,您可以使用流创建一个计算每个元素出现次数的映射,如下所示:
int[] array = {11, 14, 17, 11, 48, 33, 29, 11, 17, 22, 11, 48, 18}; Map occurrences = Arrays.stream(array) .boxed() .collect(Collectors.groupingBy( Function.identity(), Collectors.counting()));
现在,如果您只想保留多于1次的值,则只需删除值等于1
的映射条目:
occurrences.values().removeIf(v -> v == 1);
最后,如果您打印地图:
System.out.println(occurrences);
您将获得以下输出:
{48=2, 17=2, 11=4}
或者,以您期望的格式获得输出:
occurrences.forEach((k, v) -> System.out.println(k + ": "+ v));
另一种方式,更短,没有流的开销:
Map occurrences = new HashMap<>(); for (int n : array) occurrences.merge(n, 1L, Long::sum);
然后,删除前面显示的唯一元素的条目:
occurrences.values().removeIf(v -> v == 1);
您可以使用filter:
dup.stream().filter(key -> Collections.frequency(list,key)>2).forEach(System.out::println);
您根本不必将其转换为ArrayList。 看看这个:
HashSet set = new HashSet (); for (int i = 0; i < array.length; i++) { if(set.contains(array[i])) System.out.println(array[i]); else set.add(array[i]); }