按值排序并发映射条目

Dón*_*nal 7 java sorting collections concurrency

有没有办法创建一个线程安全的实现Map来维护它按值排序的条目?我知道我可以Map像这样创建一个线程安全的

ConcurrentMap<String, Double> rankings = new ConcurrentHashMap<String, Double>();
Run Code Online (Sandbox Code Playgroud)

然后我可以通过将它传递给像这样的实用程序方法来获取按值排序的条目:

public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
    List<Map.Entry<K, V>> list = new LinkedList<Map.Entry<K, V>>(map.entrySet());
    Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
        @Override
        public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
            return (o1.getValue()).compareTo(o2.getValue());
        }
    });

    Map<K, V> result = new LinkedHashMap<K, V>();
    for (Map.Entry<K, V> entry : list) {
        result.put(entry.getKey(), entry.getValue());
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

但我正在寻找的是一个线程安全的Map,它维护按值排序的条目,这样我就不必在每次插入/删除后调用上面的方法,以保持条目按值排序.我想我正在寻找一种结合了ConcurrentHashMapand 的行为的实现LinkedHashMap,但还没有找到.

ConcurrentSkipListMap几乎提供了我想要的东西,但它似乎只支持按键值排序.

Dil*_*nga 2

考虑为此构建一个复合数据结构。在较高级别上,执行以下操作。

首先,实现 Map.Entry 来保存键值对。该对的排序将首先按值排序,然后按键排序。

private static class InternalEntry<K extends Comparable<K>,
                                   V extends Comparable<V>>
        implements Comparable<InternalEntry<K, V>>,
                   Map.Entry<K, V> {
    private final K _key;
    private final V _val;

    InternalEntry(K key, V val) {
        _key = key;
        _val = val;
    }

    public K getKey() {
        return _key;
    }

    public V getValue() {
        return _val;
    }

    public V setValue(V value) {
        throw new UnsupportedOperationException();
    }

    public int compareTo(InternalEntry<K, V> o) {
        int first = _val.compareTo(o._val);
        if (first != 0) {
            return first;
        }
        return _key.compareTo(o._key);
    }
}
Run Code Online (Sandbox Code Playgroud)

整个条目可以用作有序映射的键。

但该映射不支持按键有效查找值。为了实现这一点,引入另一个映射,它将键映射到条目。

复合结构如下所示:

class OrderedByValue<K extends Comparable<K>, V extends Comparable<V>> {
    private final Map<InternalEntry<K, V>, Boolean> _ordering = 
        new TreeMap<InternalEntry<K, V>, Boolean>();

    private final Map<K, InternalEntry<K, V>> _lookup = 
        new HashMap<K, InternalEntry<K, V>>();

    public V put(K key, V val) {
        InternalEntry<K, V> entry = new InternalEntry<K, V>(key, val);
        InternalEntry<K, V> old = _lookup.put(key, entry);
        if (old == null) {
            _ordering.put(entry, Boolean.TRUE);
            return null;
        }
        _ordering.remove(old);
        _ordering.put(entry, Boolean.TRUE);
        return old.getValue();
    }

    @SuppressWarnings({"unchecked"})
    public Iterable<Map.Entry<K, V>> entrySet() {
        Iterable entries = Collections.unmodifiableSet(_ordering.keySet());
        return (Iterable<Map.Entry<K, V>>) entries;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我没有提供实现完整地图所需的所有代码 - 如果您需要其他方法的帮助,请告诉我。

如果需要支持空键/值,您还需要在InternalEntry的比较实现中执行一些特殊情况代码。