关于java:按值对并发哈希映射进行排序

Sorting a concurrent hash map by value

我是爪哇人。我想按值对并发哈希映射进行排序。我在这里找到了一种方法-按值对并发映射项排序

有更简单的方法吗?有人能举例说明吗?

谢谢。


另一种解决方案是切换到使用在Java 6中添加的EDCOX1 0。引自javadocs:

This class implements a concurrent variant of SkipLists providing expected average log(n) time cost for the containsKey, get, put and remove operations and their variants. Insertion, removal, update, and access operations safely execute concurrently by multiple threads. Iterators are weakly consistent, returning elements reflecting the state of the map at some point at or since the creation of the iterator. They do not throw ConcurrentModificationException, and may proceed concurrently with other operations. Ascending key ordered views and their iterators are faster than descending ones.

滑雪者是平衡树的概率替代品。它们与树具有相同的O,但通常它们的实现要简单得多。如果您的大多数操作都是哈希表查找(定义为O(1)),那么您将看到对于合适的表大小的性能不同,但是如果您经常需要排序,这可能是一个更好的解决方案。

我只希望Java提供了这个大数据结构的非并发版本。


根据您的使用案例,我将创建另一个类来表示您的数据结构,它由一个哈希图和一个维护值顺序的列表组成。

有关此内容的详细信息,请参阅:
按值(Java)对Brime/Value>进行分类按值排序hashmap
http://www. cordalnc.com/t/382750/java/java/排序哈希映射值

还可以扩展ConcurrentHashMap以重写EntrySet和Keyset方法,以按值的顺序返回条目/键。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class OrderedValueHashMap<K,V extends Comparable<V>> extends ConcurrentHashMap<K, V> {

@Override
public Set<Map.Entry<K, V>> entrySet() {
    Set<Map.Entry<K, V>> orderedValueEntrySet = new TreeSet<Map.Entry<K,V>>(new Comparator<Map.Entry<K,V>>() {

        @Override
        public int compare(java.util.Map.Entry<K, V> o1,
                java.util.Map.Entry<K, V> o2) {
            return o1.getValue().compareTo(o2.getValue());
        }
    });
    orderedValueEntrySet.addAll(super.entrySet());
    return orderedValueEntrySet;
}

@Override
public Set<K> keySet() {
    Set<K> orderedKeySet = new LinkedHashSet<K>();
    for(Map.Entry<K, V> e : entrySet()) {
        orderedKeySet.add(e.getKey());
    }
    return orderedKeySet;
}

}

如果您经常调用方法keyset/entryset,则上面的解决方案不是最佳的,因为它会对每个调用中的条目进行排序。您可能希望缓存这些结果,以避免在映射的内部状态未更改时重新计算。

上面的示例运行如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
    ConcurrentHashMap<String,Integer> map = new OrderedValueHashMap<String,Integer>();
    map.put("a", 3);
    map.put("b", 7);
    map.put("c", 1);
    map.put("q", 2);

    for (Map.Entry<String, Integer> entry : map.entrySet()) {
        System.out.println(entry);
    }

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

}

输出:

1
2
3
4
5
6
7
8
c=1
q=2
a=3
b=7
c
q
a
b


Is there a simpler way of doing it?

据我所知,没有。

当然,没有办法进行就地类型的并发哈希映射。CHM本质上是无序的,因此您必须将条目放入不同的数据结构中,以表示条目的有序性。

如果你告诉我们你的需求是什么,也许我们可以建议一个替代策略。