如何在Java中对复杂的HashMap结构进行排序?

时间:2014-05-26 15:00:16

标签: java list sorting hashmap frequency

我正在开发一个频率图来计算文本中的lemmata频率,同时保存它们的屈曲度。我的数据结构如下所示:

HashMap<List<String>, HashMap<List<String>, Long>> frequencyMap = ... ;

第一个列表包含一个词典序列,第二个列表包含词语的弯曲和它们的频率。有没有办法按频率计数对数据结构进行排序?

或者你会建议另一种数据结构来存储这些值,例如,更容易排序。

感谢任何帮助。

4 个答案:

答案 0 :(得分:0)

List sortedKeys=new ArrayList(yourMap.keySet());
Collections.sort(sortedKeys);

试试这个!

答案 1 :(得分:0)

您拥有的数据结构不易排序,因为您可以为每个值列表提供一组键。

例如,您将拥有一个与字符串和值列表的映射匹配的字符串列表,其中所有这些值都可以引用不同的键。

首先尝试简化数据结构。表达它的意思。然后使用TreeMap或Collections.sort,如@Lockon描述的那样。

对于TreeMap示例:http://tutorialswithexamples.com/java-treemap-tutorial-and-examples/

答案 2 :(得分:0)

有两种方法可以对此地图进行排序。基于Long值对内部地图进行排序。或者根据内部地图中的Long值对外部地图进行排序。在后一种情况下,排序将仅比较内部地图中第一项的值。我认为这是你的要求。然后你可以使用以下方法

private Map<List<String>, HashMap<List<String>, Long>> sortMap(
        Map<List<String>, HashMap<List<String>, Long>> unsortedMap) {

    List<Entry<List<String>, HashMap<List<String>, Long>>> list = new LinkedList<Entry<List<String>, HashMap<List<String>, Long>>>(
            unsortedMap.entrySet());

    Collections.sort(list,
            new Comparator<Entry<List<String>, HashMap<List<String>, Long>>>() {

                @Override
                public int compare(
                        Entry<List<String>, HashMap<List<String>, Long>> o1,
                        Entry<List<String>, HashMap<List<String>, Long>> o2) {

                    return o1.getValue().entrySet().iterator().next().getValue().compareTo(o2.getValue().entrySet().iterator().next().getValue());
                }
            });

    Map<List<String>, HashMap<List<String>, Long>> sortedMap = new LinkedHashMap<List<String>, HashMap<List<String>, Long>>();
    for(Entry<List<String>, HashMap<List<String>, Long>> item : list){
        sortedMap.put(item.getKey(), item.getValue());
    }
    return sortedMap;
}

答案 3 :(得分:0)

HashMaps不支持对元素进行排序,因此您必须首先将数据复制到允许排序的数据结构中:

ArrayList<Map.Entry<List<String>, HashMap<List<String>, Long>> items =
    new ArrayList<>(frequencyMap.entrySet());

现在,写一个与Map.Entry值相匹配的Comparator

class FrequencyComparator
implements Comparator<Map.Entry<List<String>, HashMap<List<String>, Long>> {
    public int compare(Map.Entry<List<String>, HashMap<List<String>, Long>> a,
                       Map.Entry<List<String>, HashMap<List<String>, Long>> b) {
        // code to get a's and b's frequency counts and compare them
    }
}

现在,您可以对数组进行排序:

Collections.sort(items, new FrequencyComparator());

如果获取项目的频率计数很昂贵,那么您可以为每个项目计算一次,然后对包含这些预先计算的值的数据结构进行排序:

class FrequencySortHelper implements Comparable<FrequencySortHelper> {
    final List<String> key;
    final int score;
    public FrequencySortHelper(List<String> key, HashMap<List<String>, Long>> value) {
        this.key = key;
        score = getFrequencyCount(value);
    }

    public int compareTo(FrequencySortHelper other) {
        int thisVal = this.score;
        int anotherVal = other.score;
        return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
    }
}

ArrayList<FrequencySortHelper> items = new ArrayList<>(frequencyMap.size());
for (Map.Entry<List<String>, HashMap<List<String>, Long>> item : frequencyMap.entrySet()) {
    items.add(new FrequencySortHelper(item.key(), item.value()));
}

Collections.sort(items);  // Uses FrequencySortHelper's compareTo()

如果您认为所有这些Map.Entry<List<String>, HashMap<List<String>, Long>>内容都很尴尬,那么您是对的。您应该考虑定义一些对象来包含这些数据,而不是仅仅将集合串联在一起。