的队列确保唯一性元素的?
-
22-09-2019 - |
题
我在寻找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);}
};