巨大的Hashtable排序 - 值的数量 - 553685

时间:2012-10-05 05:21:57

标签: java sorting hashtable

我创建了一个hashmap来存储多个文件中的单词出现,例如10,000个文本文件。然后我想从hashmap中排序并打印前10个单词。 Hashmap定义为,

      Hashtable <String, Integer> problem1Counter = new Hashtable<String, Integer> ();

当我将文件保存到1000左右时,我能够使用这样的简单排序获得前十个单词,

String[] keysProblem1 = (String[]) problem1Counter.keySet().toArray(new String[0]);
  Integer [] valuesProblem1 =  (Integer[])problem1Counter.values().toArray(new Integer[problem1Counter.size()]);

int kk = 0;      String ii = null;

    for (int jj = 0; jj < valuesProblem1.length ; jj++){
        for (int bb = 0; bb < valuesProblem1.length; bb++){
            if(valuesProblem1[jj] < valuesProblem1[bb]){
            kk = valuesProblem1[jj];
            ii = keysProblem1[jj];
            valuesProblem1[jj] = valuesProblem1[bb];
            keysProblem1[jj] = keysProblem1[bb];
            valuesProblem1 [bb] = kk;
            keysProblem1 [bb] = ii;}}}

因此,当散列表的值超过553685时,上述方法无效。那么有人能建议并展示一种更好的方法来对它们进行排序吗我是java的新手,但曾参与过动作,所以我觉得有点舒服。 感谢。

3 个答案:

答案 0 :(得分:4)

当你分开keysvalues并尝试保持每个索引连接的东西时,你的问题就开始了。相反,保持它们耦合,并对java给你的Map.Entry对象进行排序。

我不确定这会编译,但它应该给你一个开始。

// HashMap and Hashtable are very similar, but I generally use HashMap.
HashMap<String, Integer> answers = ...

// Get the Key/Value pairs into a list so we can sort them.
List<Map.Entry<String, Integer>> listOfAnswers =
    new ArrayList<Map.Entry<String, Integer>>(answers.entrySet());

// Our comparator defines how to sort our Key/Value pairs.  We sort by the
// highest value, and don't worry about the key.
java.util.Collections.sort(listOfAnswers,
    new Comparator<Map.Entry<String, Integer>>() {
        public int compare(
                Map.Entry<String, Integer> o1,
                Map.Entry<String, Integer> o2) {
            return o2.getValue() - o1.getValue();
        }
    });

// The list is now sorted.
System.out.println( String.format("Top 3:\n%s: %d\n%s: %d\n%s: %d", + 
        listOfAnswers.get(0).getKey(), listOfAnswers.get(0).getValue(), 
        listOfAnswers.get(1).getKey(), listOfAnswers.get(1).getValue(), 
        listOfAnswers.get(2).getKey(), listOfAnswers.get(2).getValue()));

答案 1 :(得分:3)

为了更好地进行排序,我会这样做:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
    HashMap<String, Integer> counter = new HashMap<String, Integer>();

    // [... Code to populate hashtable goes here ...]
    // 

    // Extract the map as a list
    List<Map.Entry<String, Integer>> entries = new ArrayList<Map.Entry<String, Integer>>(counter.entrySet());

    // Sort the list of entries.
    Collections.sort(entries, new Comparator<Map.Entry<String, Integer>>() {
        @Override
        public int compare(Entry<String, Integer> first, Entry<String, Integer> second) {
        // This will give a *positive* value if first freq < second freq, zero if they're equal, negative if first > second.
        // The result is a highest frequency first sort.
        return second.getValue() - first.getValue();
        }
    });

    // And display the results
    for (Map.Entry<String, Integer> entry : entries.subList(0, 10))
        System.out.println(String.format("%s: %d", entry.getKey(), entry.getValue()));
    }

}

编辑解释其工作原理

您的原始算法看起来像Selection Sort的变体,它是一种O(n ^ 2)算法。您的变体也进行了大量的额外交换,因此非常慢。

如果你的问题大小乘以10,那么O(n ^ 2)的运行时间通常要长100倍。排序50万个元素需要进行2500亿次比较,其中许多将导致交换。

Collections#sort中的内置排序算法是Merge Sort的快速变体,它在O(n.log(n))时间内运行。这意味着每次将问题大小乘以10时,它只需要大约30倍的时间。对半个元素进行排序只需要进行大约1000万个比较。

这就是为什么有经验的开发人员会建议您尽可能使用库函数。编写自己的排序算法对于学习来说非常有用,但是实现一个算法需要花费很多工作,因为它可以像库中的那样快速灵活地实现。

答案 2 :(得分:1)

  • 创建一个实现Comparable的内部类Word
  • 覆盖public int compareTo(Word w)以使其使用出现次数
  • 创建一个HashMap大小的单词数组
  • 填充遍历HashMap的数组
  • 在数组
  • 上调用Arrays.sort

或者,因为你只需要前10名,所以你可以在你的单词中迭代并保持前十名。