数据结构按值对元素进行排序

时间:2015-05-27 08:39:16

标签: java sorting data-structures associative-array

我需要一个Java中的数据结构,它可以操作String,计算ArrayList<String>中每个单词的频率,然后我需要根据频率对它们进行排序。

简单地说,数据结构需要是关联数组,可以按 BY VALUES 进行排序,我已经将这些行放入{{1}并且对无法排序这一事实感到惊讶,现在我不得不考虑另一种数据结构。

P.S。 (使用两个列表不适合我的程序,因为它需要进行大量的计算,所以如果单个结构保存每个HashMap及其出现而不是String的列表会更好s和另一个频率)。

编辑:我很感激帮助,但有些人建议String,所以我想在这里指定一些内容:我需要按字符串的出现排序结构(在{{1}的情况下)这是值而不是键)。

5 个答案:

答案 0 :(得分:4)

HashMap没有排序,实际上也不应该这样。如果您希望对条目进行排序,则可以使用SortedMap个实现之一,例如TreeMap

TreeMap有一个构造函数,如果您有非标准Comparator,可以帮助您(例如,如果您想要对String进行自然排序):

TreeMap(Comparator<? super K> comparator)

UPD :我错过了这一点,您需要按值对条目进行排序。

在这种情况下,我没有看到任何解决方案,除了那个,你只需要对条目进行几次排序,而不是保持这种状态。

您可以使用任何Map,例如,留在HashMap,但在处理之前,您可以对条目进行排序:

Set<Map.Entry<String, Integer>> entries = map.entrySet();
Set<Map.Entry<String, Integer>> sorted = new TreeSet<>(
        Comparator.comparingInt(Map.Entry::getValue).reversed()); // it's Java 8, but you may extract this lambda
sorted.addAll(entries);
for (Map.Entry<String, Integer> entry: sorted) {
    //...
    // the entries will be sorted by value
}

准确地说,您不能以任何类型Map来维护以这种方式排序的条目,因为键的顺序只设置一次而您无法更改它,因为:

  1. 这不是常规的,Comparator / compareTo运算符应该在运行时给出相同的结果(这就是Map s中不能理解可变类的原因)
  2. 预计这不会给你一些明显的结果,一般不会对键进行重新排序。

答案 1 :(得分:2)

我认为没有简单的数据结构。

收集频率数据时频率会发生变化。在收集所有字符串频率之后应该进行哪种排序。

我能想到的最简单的方法是:

// psuedo-code
final Map<String, Integer> stringFreq = ....; // it doesn't matter what kind of impl you use

// collect the String vs frequency in stringFreq

Map<String, Integer> result = new TreeMap<String, Integer>(stringFreq, 
        new Comparator<String> {
        @Override
            public int compare(String a, String b) {
                int aFreq = stringFreq.get(a);
                int bFreq = stringFreq.get(b);
                return (aFreq==bFreq)?a.compareTo(b) : (aFreq-bFreq);
            }
        });


// result should have data sorted by frequency, and then the string value

答案 2 :(得分:1)

Java有一个SortedMap接口,有两个实现。最简单的是TreeMap

答案 3 :(得分:1)

另一种解决方案,使用自定义bean和简单列表。

1 /定义自定义bean

public class StringOccurence {
  String string ;
  int occurrence ;
}

2 /创建比较器

public class StringOccurrenceComparator implements Comparator<StringOccurence> {
  @Override
  public int compare(StringOccurrence so1, StringOccurrence so2) {
    return Integer.compare(so1.occurrence, so2.occurrence);
  }
}

3 /使用比较器对列表进行排序

List<StringOccurrence> list = constructList();
Collections.sort(list, new StringOccurrenceComparator());

如果你幸运地使用java8,这里是第2点和第3点的简短版本:

List<StringOccurrence> list = constructList();
Collections.sort(list, (so1, so2) -> Integer.compare(so1.occurrence, so2.occurrence));

答案 4 :(得分:1)

如果您使用maxheap数据结构存储字符串及其频率出现值,并且始终将最大值频率保持在顶部,那您可以简单地一次性获得最大频率的字符串,但是复杂度高这里将是重新计算和调整最大堆,所以这实际上取决于您希望看到更多的单词数量或单词变化频率很大的变化。