关于java:排序HashSets的集合

Sorting a collection of HashSets

如果这是一个副本,我道歉,但我找不到任何具体回答这个问题的答案。

我有一个hashmap,其中包含一个字符串键和一个设置值。我想根据集合的长度对地图中的值进行排序。考虑:

1
HashMap<String, Set<String>> myMap;

包含:

1
2
3
4
5
{"A", {"Dukmerriot","King","Pumpkin"}}  
{"B", {"Steve"}}
{"C", {"Jib","Jab","John","Julie"}}
{"D", {"Apple","Amy","Unicorn","Charlie","Raptor"}}
{"E", {}}

我希望能够有效地从myMap中得到列表{"D","C","A","B", E"}(它指定集合的顺序从大到小)。

除了创建一个实现set并重写compareTo方法的包装类之外,是否有一种方法根据集合的长度对其进行排序?

编辑:我应该指定不需要使用哈希映射来维护这个集合。我可以使用treemap或其他东西,但我不确定这是否可行,因为set不能实现可比性。


Is there a way to sort a collection of sets based on their length other than creating a wrapper class that implements Set and overriding the compareTo method?

这是一种完全可行的方法。您也可以使用Comparator

1
2
3
4
5
6
7
List<Set<String>> mySets = new ArrayList<>(myMap.values());
mySets.sort(new Comparator<Set<String>>() {
    @Override
    public int compare(Set<String> a, Set<String> b) {
        return Integer.compare(a.size(), b.size());
    }
});

…但是现在您已经丢失了每个集合的对应键。让我们对地图条目进行排序!

1
2
3
4
5
6
7
List<Entry<String, Set<String>>> entries = new ArrayList<>(myMap.entrySet());
entries.sort(new Comparator<Entry<String, Set<String>>>() {
    @Override
    public int compare(Entry<String, Set<String>> a,Entry<String, Set<String>> b) {
        return Integer.compare(a.getValue().size(), b.getValue().size());
    }
});

现在你可以"轻松"拿到钥匙:

1
2
3
4
List<String> sortedKeys = new ArrayList<>();
for (Entry<String, Set<String>> e : entries) {
    sortedKeys = e.getKey();
}

这个列表不会是密钥的实况视图,但如果这是一个可接受的限制,它将是您的最佳选择。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
final Map<String, Set<String>> map = new HashMap<>();

map.put("A", ImmutableSet.of("Dukmerriot","King","Pumpkin"));
map.put("B", ImmutableSet.of("Steve"));
map.put("C", ImmutableSet.of("Jib","Jab","John","Julie"));
map.put("D", ImmutableSet.of("Apple","Amy","Unicorn","Charlie","Raptor"));
map.put("E", new HashSet<String>());

List<String> keys = new ArrayList<>(map.keySet());
Collections.sort(keys, new Comparator<String>() {

    @Override
    public int compare(String o1, String o2) {
        return Integer.valueOf(map.get(o2).size()).compareTo(map.get(o1).size());
    }
});

for (String key : keys) {
    System.out.println(key);
}

印刷品

1
2
3
4
5
D
C
A
B
E

我使用了谷歌的guava的不变集,只是为了缩短代码。你可能想看看他们的多重映射,因为你会发现它很有用。


我将创建一个自定义对象来同时保存SetString。让类实现Comparable,实现使用设置的大小。然后用一个List把它填满,用Collections.sort()得到想要的结果。

1
2
3
4
5
6
7
8
9
10
11
class A implements Comparable {
    Set set;
    String string;

    ...constructor etc....

    @Override
    public int compare(A a,A b) {
        return Integer.compare(a.set.size(), b.set.size());
    }
}

由于HashMaps不维护内部秩序,你不能这样做。你能做的最好的事情就是用map.values()获取所有的值,迭代它,看看哪个值最长。

1
2
3
4
5
6
7
8
9
10
HashMap<T, V> map = ...
Collection<V> values = map.values();

int maxLen = Integer.MIN_VALUE;
Set<String> winner = null;
for(V v : values) {
   if(v.size() > maxLen) {
     winner = v;
   }
}

TV是任意类型。在你的例子中,t等于字符串,v等于集合。


哈希图不可排序。它们经过优化,可以通过键查找值。