按值对并发哈希映射进行排序

时间:2012-05-14 22:42:41

标签: java concurrency hash map

我是java的新手。 我想按值对并发哈希映射进行排序。我在这里找到了一种方法 - sort concurrent map entries by value

有更简单的方法吗?有人可以用一个例子解释一下吗?

感谢。

3 个答案:

答案 0 :(得分:4)

另一个解决方案是切换到使用Java 6中添加的ConcurrentSkipListMap。引用Javadocs:

  

此类实现SkipLists的并发变体,为containsKey,get,put和remove操作及其变体提供预期的平均log(n)时间成本。插入,删除,更新和访问操作由多个线程安全地同时执行。迭代器是弱一致的,在迭代器创建时或之后的某个时刻返回反映地图状态的元素。它们不会抛出ConcurrentModificationException,并且可能与其他操作同时进行。升序键有序视图及其迭代器比降序视图快。

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

我只希望Java提供这种优秀数据结构的非并发版本。

答案 1 :(得分:2)

根据你的用例,我会创建另一个代表你的数据结构的类,它由一个hashmap和一个列表组成,用于维护值的排序。

有关此内容的更多详情:
Sort a Map<Key, Value> by values (Java)
Sorting HashMap by values
http://www.coderanch.com/t/382750/java/java/Sorting-HashMap-values

您还可以扩展ConcurrentHashMap以覆盖entrySet和keySet方法,以按值的顺序返回条目/键。

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,则上述解决方案不是最佳,因为它会对每次调用的条目进行排序。您可能希望缓存这些结果,以避免在地图的内部状态未发生更改时重新计算。

上述示例运行如下:

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);
    }

}

输出:

c=1
q=2
a=3
b=7
c
q
a
b

答案 2 :(得分:1)

  

有更简单的方法吗?

据我所知,没有。

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

如果您告诉我们您的要求是什么,也许我们可以提出另一种策略。