我在寻找java.util.Queue中的实现什么的谷歌收集谁表现得像一个队列中,同时也保证了队列中的每个元素都是独一无二的。 (所有进一步插入将没有任何效果)

这是可能的,否则我将不得不做手工?

有关我现在正在使用一个队列,用链表实现,以及我插入之前检查唯一性。 (我用一个侧地图这样做,从侧面映射/前queu后添加/删除元素)。我不喜欢太多。

任何输入是受欢迎的。如果它不是在java.util包中,那么也许这是一个坏主意?

有帮助吗?

解决方案

怎么样 LinkedHashSet ?其迭代蜜饯插入顺序,但因为它是一个Set,其元素是唯一的。

作为它的文件说,

  

请注意,插入顺序是的影响如果一个元素是重新插入的入套。

为了有效地从这一“排队”的头部删除元素,经过它的迭代器:

Iterator<?> i = queue.iterator();
...
Object next = i.next();
i.remove();

其他提示

这不,据我知道,但将是相当简单的与LinkedList结合使用Set实施存在:

/**
 * Thread unsafe implementation of UniqueQueue.
 */
public class UniqueQueue<T> implements Queue<T> {
  private final Queue<T> queue = new LinkedList<T>();
  private final Set<T> set = new HashSet<T>();

  public boolean add(T t) {
    // Only add element to queue if the set does not contain the specified element.
    if (set.add(t)) {
      queue.add(t);
    }

    return true; // Must always return true as per API def.
  }

  public T remove() throws NoSuchElementException {
    T ret = queue.remove();
    set.remove(ret);
    return ret;
  }

  // TODO: Implement other Queue methods.
}

我被诱惑保持 HashSet的含有唯一地标识该项目在队列侧由端与它的密钥。然后,只需检查HashSet的,看看该项目是在队列中添加它之前。当从队列中删除项目,只需删除从HashSet的密钥,以及

检查过程的独特性是有代价的(无论是在空间或时间)。好像它可能来自像一个PriorityQueue,这将维持一个堆排序由要素的比较是很有意思的工作。您也许能够杠杆作用,以更有效地(O(log n)的)检查是否存在不维护一个侧面映射。

如果你想换一个队列与唯一性检查,我会强烈建议使用谷歌集合的 ForwardingQueue 以建立这样的事情。

只是为了完成亚当斯基的回答是:

/**
 * A queue that keeps each element only once. 
 * If you try to add an element that already exists - nothing will happen.
 * 
 * @author Adamski http://stackoverflow.com/a/2319156/827927
 * @NotThreadSafe
 */
public class UniqueQueue<T> implements Queue<T> {

private final Queue<T> queue = new LinkedList<T>();
private final Set<T> set = new HashSet<T>();

@Override public boolean add(T t) {
    // Only add element to queue if the set does not contain the specified element.
    if (set.add(t))
        queue.add(t);
    return true; // Must always return true as per API def.
}

@Override public boolean addAll(Collection<? extends T> arg0) {
    boolean ret = false;
    for (T t: arg0)
        if (set.add(t)) {
            queue.add(t);
            ret = true;
        }
    return ret;
}

@Override public T remove() throws NoSuchElementException {
    T ret = queue.remove();
    set.remove(ret);
    return ret;
}

@Override public boolean remove(Object arg0) {
    boolean ret = queue.remove(arg0);
    set.remove(arg0);
    return ret;
}

@Override public boolean removeAll(Collection<?> arg0) {
    boolean ret = queue.removeAll(arg0);
    set.removeAll(arg0);
    return ret;
}

@Override public void clear() {
    set.clear();
    queue.clear();
}

@Override public boolean contains(Object arg0) {
    return set.contains(arg0);
}

@Override public boolean containsAll(Collection<?> arg0) {
    return set.containsAll(arg0);
}

@Override public boolean isEmpty() {
    return set.isEmpty();
}

@Override public Iterator<T> iterator() {
    return queue.iterator();
}

@Override public boolean retainAll(Collection<?> arg0) {
    throw new UnsupportedOperationException();
}

@Override public int size() {
    return queue.size();
}

@Override public Object[] toArray() {
    return queue.toArray();
}

@Override public <T> T[] toArray(T[] arg0) {
    return queue.toArray(arg0);
}

@Override public T element() {
    return queue.element();
}

@Override public boolean offer(T e) {
    return queue.offer(e);
}

@Override public T peek() {
    return queue.peek();
}

@Override public T poll() {
    return queue.poll();
}
}

这是一个很好的问题。没有现成的简单的解决方案。我会来挖了一些代码,我写了一段时间后一些试图做到这一点,回来编辑这个答案。

修改我回来了。诚然,如果你不需要并发,你最好单独维护队列并设置。因为我在做什么,并发性是一个目标,但最好的解决方案,我能想出因为约束是有问题的;基本上,因为它使用的ConcurrentHashMap,更多的你从队列中删除了“head”元素(一个基本的东西做的一个队列),越不平衡哈希表会随着时间的推移。我还可以与你分享这段代码,但我怀疑你真的想要它。

修改:用于并发哪里需要我给此答案的情况下: 并行设置队列

不幸的是它不存在。因为我需要这样的队列我已经开发出一种阻塞队列支持由一组,由激发的 java.util.concurrent.LinkedBlockingQueue中

您可以在这里找到:

https://github.com/bvanalderweireldt/concurrent-unique-queue

示例:

final BlockingQueue<Integer> queue = new ConcurrentSetBlockingQueue<>(1);
queue.offer(new Integer(1)); //True
queue.offer(new Integer(1)); //False

可以与Maven使用它:

<dependency>
  <groupId>com.hybhub</groupId>
  <artifactId>concurrent-util</artifactId>
  <version>0.1</version>
</dependency>

我有点晚了回答,但我最终使用的ArrayDeque并重写add方法,我需要解决类似的问题。

    Deque<Long> myQueue = new ArrayDeque<Long>() {
        @Override
        public boolean add(Long e) { return !this.contains(e) && super.add(e);}
    };
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top