我正在寻找java.util.Queue的实现或Google集合中某些行为类似于Queue的实现,但还要确保队列中的每个元素都是唯一的。(所有进一步插入均无效)
有这种可能,还是我必须手工做?
现在,我正在使用带有LinkedList实现的Queue,并在插入之前检查其唯一性。(我使用侧面图进行此操作,在排队之前/之后在侧面图中添加/删除元素)。我不太喜欢
欢迎任何输入。如果它不在java.util包中,那可能不是一个好主意?
我正在寻找java.util.Queue的实现或Google集合中某些行为类似于Queue的实现,但还要确保队列中的每个元素都是唯一的。(所有进一步插入均无效)
有这种可能,还是我必须手工做?
现在,我正在使用带有LinkedList实现的Queue,并在插入之前检查其唯一性。(我使用侧面图进行此操作,在排队之前/之后在侧面图中添加/删除元素)。我不太喜欢
欢迎任何输入。如果它不在java.util包中,那可能不是一个好主意?
Answers:
怎么样LinkedHashSet
?它的迭代器保留插入顺序,但是由于它是a Set
,因此其元素是唯一的。
如其文档所述,
请注意,如果将元素重新插入到集合中,则插入顺序不会受到影响。
为了有效地从此“队列”的头部删除元素,请经历其迭代器:
Iterator<?> i = queue.iterator();
...
Object next = i.next();
i.remove();
据我所知,这并不存在,但是将aLinkedList
与a结合使用将非常容易实现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.
}
return true
中add
。是不是有合同之间的冲突Collection#add
和Queue#add
?该集合应该保证唯一性,因此应false
根据Collection
javadoc返回。同时,Queue
javadoc明确提到该方法是返回true
或引发异常。docs.oracle.com/javase/7/docs/api/java/util/Queue.html#add(E)docs.oracle.com/javase/7/docs/api/java/util / ...不确定其中哪一个在这种情况下,应遵循两个合同。
我很想维护一个HashSet,其中包含一个键,该键唯一地标识队列中与之并列的项。然后,只需在添加之前检查HashSet即可查看该项目是否在队列中。从队列中删除项目时,也只需从HashSet中删除密钥。
当然,检查唯一性是有代价的(在空间或时间上)。从PriorityQueue之类的东西进行工作似乎很有趣,该工作将维护按元素的Comparator排序的堆。您可能可以利用它来更有效地(O(log n))检查是否存在,而无需维护侧视图。
如果您确实想使用唯一性检查器包装Queue,我强烈建议您使用Google Collections ForwardingQueue来构建这样的东西。
只是为了完成Adamski的答案:
/**
* 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();
}
}
不幸的是它不存在。由于我需要这样的队列,因此我开发了一个受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>