Java ConcurrentMap - 键在Map中的位置

时间:2012-04-26 06:31:04

标签: java treemap fifo

我有一个有趣的问题,我希望得到一些帮助。我已经为两个独立的条件实现了几个队列,一个基于FIFO和一个键的另一个自然顺序(ConcurrentMap)。也就是说,您可以将两个队列的图像都按照不同的顺序排列。我有问题(我正在寻找一种有效的方法)如果我在ConcurrentMap中找到基于某些标准的关键字,那么在FIFO映射中找到关键字“位置”的最佳方法是什么。基本上我想知道它是第一键(这很容易),还是说它是第10键。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

没有用于访问FIFO映射中的订单的API。您可以执行此操作的唯一方法是迭代keySet()values()entrySet()并计算。

答案 1 :(得分:0)

如果您可以使用ConcurrentNavigableMap,则headMap的大小可以为您提供所需内容。

答案 2 :(得分:0)

我相信下面的代码可以完成这项工作。我已经离开了元素的实现 - >键作为抽象方法。请注意,计数器用于为元​​素分配增加的数字。另请注意,如果多个线程调用add(...),则FIFO中的元素只是松散排序。这迫使花哨的max(...)min(...)逻辑。这也是位置近似的原因。第一个也是最后一个是特例。首先可以清楚地表明。最后是棘手的,因为当前的实现返回一个真正的索引。

由于这是一个大概的位置,我建议您考虑让API在float0.0之间返回1.0,以指示队列中的相对位置。

如果您的代码需要使用pop(...)以外的其他方式支持删除,则需要使用大致大小,并将返回值更改为((id - min) / (max - min)) * size,并使用所有相应的int / float施放&四舍五入。

public abstract class ApproximateLocation<K extends Comparable<K>, T> {

    protected abstract K orderingKey(T element);

    private final ConcurrentMap<K, Wrapper<T>> _map = new ConcurrentSkipListMap<K, Wrapper<T>>();
    private final Deque<Wrapper<T>> _fifo = new LinkedBlockingDeque<Wrapper<T>>();
    private final AtomicInteger _counter = new AtomicInteger();

    public void add(T element) {
        K key = orderingKey(element);
        Wrapper<T> wrapper = new Wrapper<T>(_counter.getAndIncrement(), element);
        _fifo.add(wrapper);
        _map.put(key, wrapper);
    }

    public T pop() {
        Wrapper<T> wrapper = _fifo.pop();
        _map.remove(orderingKey(wrapper.value));
        return wrapper.value;
    }

    public int approximateLocation(T element) {
        Wrapper<T> wrapper = _map.get(orderingKey(element));
        Wrapper<T> first = _fifo.peekFirst();
        Wrapper<T> last = _fifo.peekLast();
        if (wrapper == null || first == null || last == null) {
            // element is not in composite structure; fifo has not been written to yet because of concurrency
            return -1;
        }
        int min = Math.min(wrapper.id, Math.min(first.id, last.id));
        int max = Math.max(wrapper.id, Math.max(first.id, last.id));
        if (wrapper == first || max == min) {
            return 0;
        }
        if (wrapper == last) {
            return max - min;
        }
        return wrapper.id - min;
    }

    private static class Wrapper<T> {
        final int id;
        final T value;

        Wrapper(int id, T value) {
            this.id = id;
            this.value = value;
        }
    }
}