Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 根据出现频率排列列表中的元素(具有重复元素)_Java_Collections - Fatal编程技术网

Java 根据出现频率排列列表中的元素(具有重复元素)

Java 根据出现频率排列列表中的元素(具有重复元素),java,collections,Java,Collections,根据列表中元素出现的频率来排列列表中元素(包含重复元素)的好方法是什么 我需要使用列表中前5个经常出现的项目 我正在考虑使用HashMap来计算元素的频率,每次元素出现时,通过增加相应的计数器&然后进行HashMap迭代5次,以在每次迭代中找到最高频率的元素。这种方法怎么样 维护一张包含计数的地图 public static Map <Foo,Integer>; 公共静态地图; 类Foo实现比较器{ 私人酒吧元素; 公共整数比较(Foo f1,Foo f2){ 返回SomeC

根据列表中元素出现的频率来排列列表中元素(包含重复元素)的好方法是什么

我需要使用列表中前5个经常出现的项目


我正在考虑使用HashMap来计算元素的频率,每次元素出现时,通过增加相应的计数器&然后进行HashMap迭代5次,以在每次迭代中找到最高频率的元素。

这种方法怎么样

维护一张包含计数的地图

public static Map  <Foo,Integer>;
公共静态地图;

类Foo实现比较器{
私人酒吧元素;
公共整数比较(Foo f1,Foo f2){
返回SomeClass.map.get(f1)-SomeClass.map.get(f2);
}
}
只需在
列表中使用update更新地图即可

使用
addFooToList()
removeFooFromList()
强制包装对列表的访问,并在其中封装映射更新逻辑。

您可以使用和


关于性能。当然,这取决于您有多少不同的值,但是在我的机器上,这个测试代码花费了大约一秒钟的时间。我认为这对于1000万件物品来说是合理的:

Multiset<Integer> set = HashMultiset.create();
int amount = 10000000;
Random random = new Random();
for (int i = 0; i < amount; i++) {
    set.add(Integer.valueOf(random.nextInt(255)));
}
TreeSet<Entry<Integer>> sortedEntries = Sets.newTreeSet(
        new Comparator<Entry<Integer>>() {
    public int compare(Entry<Integer> a, Entry<Integer> b) {
        return Ints.compare(a.getCount(), b.getCount());
    }
});
Iterables.addAll(sortedEntries, set.entrySet());
for (Entry<Integer> entry : Iterables.limit(sortedEntries, 5)) {
    System.out.println(entry.getElement());
}
Multiset set=HashMultiset.create();
整数金额=10000000;
随机=新随机();
对于(int i=0;i
我也会使用HashMap。我找到了一些代码,我就是这么做的:

HashMap<String, Integer> counts = new HashMap<String, Integer>();

void increment(String s) {
    Integer oldCount = counts.get(s);
    if (oldCount == null) {
        counts.put(s, 1);
    } else {
        counts.put(s, oldCount + 1);
    }
}
HashMap counts=newhashmap();
无效增量(字符串s){
整数oldCount=counts.get(s);
如果(oldCount==null){
计数。放置(s,1);
}否则{
计数。放置(s,oldCount+1);
}
}
列出要素:

Map.Entry<String, Integer>[] array = new Map.Entry[counts.size()];
counts.entrySet().toArray(array);
Arrays.sort(array, new Comparator<Map.Entry<String, Integer>>() {
    public int compare(Map.Entry<String, Integer> a, Map.Entry<String, Integer> b) {
        return b.getValue() - a.getValue();
    }
});
int x = 0, min = 0;
for (Map.Entry<String, Integer> el : array) {
    String k = el.getKey();
    println("Count: " + el.getValue() + "\n" + k + "\n\n");
}
Map.Entry[]数组=新的Map.Entry[counts.size()];
counts.entrySet().toArray(数组);
sort(数组,新的比较器(){
公共整数比较(Map.Entry a、Map.Entry b){
返回b.getValue()-a.getValue();
}
});
int x=0,min=0;
用于(Map.Entry el:array){
字符串k=el.getKey();
println(“计数:“+el.getValue()+”\n“+k+”\n\n”);
}

任何基于比较的排序都会产生
O(N logn)
或更高的时间复杂度,因此(渐进地)这些都不是好的建议

您的方法具有
O(N)
时间复杂度,这是您所能得到的最好结果。您可以尝试降低该常数(目前正在对列表中的元素进行大致
6*N
访问)

我会在两次迭代中这样做:首先使用HashMap计算频率。接下来,迭代映射中的条目,并保持一个有序的5元素数组,其中包含迄今为止最常见的5个值。对于每个新元素,检查该值是否比目前最常见的第五个值更常见,并在必要时更新“前5个”



更新一个更简单的解决方案,具有相同的时间复杂性。首先,计算频率使用。接下来,将所有条目放入a中,并弹出五个值。条目应为值-频率对,可通过频率进行比较(如@Jigar的解决方案)。这样的排序不会“与equals一致”(请参阅以获取解释),但这没关系。

听起来非常复杂me@Sean如果你使用的是小列表,那么写复杂的解决方案就不值得了。但是当你使用大列表(比如1000万个元素)时,你会注意到性能上的差异。没错,但是我建议的Guava Multiset是高度优化的数据结构,它们足够快(请参阅我添加的代码)@Sean好的,它们可能够快(我对你的答案投了赞成票),但作为一名兼职理论计算机科学家,我不得不吹毛求疵;)谢谢,但你必须意识到,番石榴的家伙也是电脑迷:-)a)这只会在多个对象“相同”而不是“相等”时起作用。b) 它将计数保留在被计数的对象内。我认为那是个糟糕的设计。一根香蕉不需要知道我的肚子里有多少根香蕉fridge@Jigar好的,那么你将不得不更新所有相等对象的频率,无论何时你放置或获取一个对象,这将比needed@Sean不,如果我们使用map(第二种方法),我们将不必这样做。我们还可以将
List
包装到某个类,该类具有
add/removeFooTo/FromList()
,该类封装了logic@Jigar是的,如果你删除第一种方法,我将更新你的答案:-)@Jigar好的,你在那里抓住了我:-)+1
Map.Entry<String, Integer>[] array = new Map.Entry[counts.size()];
counts.entrySet().toArray(array);
Arrays.sort(array, new Comparator<Map.Entry<String, Integer>>() {
    public int compare(Map.Entry<String, Integer> a, Map.Entry<String, Integer> b) {
        return b.getValue() - a.getValue();
    }
});
int x = 0, min = 0;
for (Map.Entry<String, Integer> el : array) {
    String k = el.getKey();
    println("Count: " + el.getValue() + "\n" + k + "\n\n");
}