【问题标题】:Sorting a concurrent hash map by value [closed]按值对并发哈希图进行排序[关闭]
【发布时间】:2012-05-14 22:42:40
【问题描述】:

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

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

谢谢。

【问题讨论】:

  • 哈希图没有特别的顺序。你的最终目标是什么?
  • 这个问题可能会有所帮助:(按值排序地图)stackoverflow.com/questions/2889443/…
  • 可能会破坏并发性。将其复制到另一个地图并使用常规方法按值对该地图进行排序。
  • 您可以将this idea (95 points answer) 应用到@Gray 提出的ConcurrentSkipListMap

标签: java concurrency hash map


【解决方案1】:

另一种解决方案是改用 Java 6 中添加的 ConcurrentSkipListMap。引用 Javadocs:

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

SkipLists 是平衡树的概率替换。它们与树具有相同的O,但通常它们的实现明显更简单。如果您的大部分操作都是哈希表查找(定义为O(1)),那么您会发现对于合适的表大小而言性能会有所不同,但如果您需要经常进行排序,这可能是一个更好的解决方案。

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

【讨论】:

  • ConcurrentSkipListMap 的非并发版本在何种情况下优于TreeMap
  • 速度。跳过列表区域通常比其他树实现更快。
  • 老实说,如果 JDK 作者没有对其进行基准测试,我会感到非常震惊,但我怀疑树在支持 NavigableMap 的“通才”特性方面也更好一些。
【解决方案2】:

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

更多详情请点击此处:
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

【讨论】:

    【解决方案3】:

    有没有更简单的方法?

    据我所知,没有。

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

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

    【讨论】:

    • 感谢您的回复。并发哈希映射的形式为 - ConcurrentMap stringFrequencyMap = new ConcurrentHashMap;我需要能够根据值(即频率)进行排序
    • @user379151 - 不够详细。这是一次性活动吗?表需要保持排序吗?是否允许该操作阻止并发更新?以此类推。
    • @user379151 - 例如,如果这是一次性的并且表格不需要“保持排序”,那么只需将地图的条目集复制到列表或数组,然后对其进行排序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多