没有重复的集合(基于 id)但保留最高版本号

Collection without duplicates (based on id) but keeps the highest version number

这似乎应该有一个标准的解决方案,但我找不到我要找的东西。手动实现并不难,但也许我的工具箱中缺少一个工具?

在伪代码中,我想要一个类似集合的集合,给定现有条目

{id_1, v_1}, {id_2, v_2}

调用addAll()
{id_1, v_2}, {id_2, v_1}

将剩下

{id_1, v_2}, {id_2, v_2}

即原来的 id_1 被更新的版本取代;原来的 id_2 仍然存在,因为它比传入的更新。

我浏览了 Guava,但没有发现任何问题。我对 Apache 集合不是很熟悉,也许可以从中构建一些东西?

谢谢大家

将对列表按版本号升序排序,然后 put 按此顺序排列成 java.util.HashSet.

您可以包装地图并提供其他方法来检查项目版本。

这里是put方法,例如

class MyMap<ID, E> extends HashMap<ID, E extends Versioned & HasId<ID>> {

public void put(E elem) {
    if (containsKey(elem.getId()) {
        E exist = get(elem.getId());
        if (elem.version.isGreater(exist.version)) super.put(elem.getId(), elem);
    } else {
        super.put(elem.getId(), elem);
    }
}

我建议使用 Map 而不是 Set,因为 this 问题。

为了避免扩展 Map,您可以非常简单地发展自己的:

class KeepBestMap<K, V> {

    final Map<K, V> map;
    final Comparator<V> compare;

    public KeepBestMap(Map<K, V> map, Comparator<V> compare) {
        this.map = map;
        this.compare = compare;
    }

    public KeepBestMap(Comparator<V> compare) {
        this(new HashMap<>(), compare);
    }

    public KeepBestMap() {
        // A null compare will assume objects are comparable.
        this(null);
    }

    public Map<K, V> getMap() {
        return map;
    }

    public V put(K key, V value) {
        // Put the new one in - note the old one.
        V replaced = map.put(key, value);
        if (replaced != null) {
            // Decide which to keep.
            // If compare not supplied assume items are Comparable.
            if ((compare != null
                    ? // Use it.
                    compare.compare(replaced, value)
                    : // Assume values are comparable - if they are not then an exception will be thrown (like TreeMap).
                    ((Comparable<V>) replaced).compareTo(value)) > 0) {
                // Put the old one back in.
                map.put(key, replaced);
                // Didn't actually replace it in the end.
                replaced = null;
            }
        }
        return replaced;
    }
}