This is how I understood the question and would take the challenge:
A task wrapper wraps a task or command and adds the additional values, the delay for the task and the identifier. I understood, that two tasks may have the same 'key', so we can't just take the tasks hashvalue.
public TaskWrapper<T> {
private T task;
private long delayInMillis;
private long key;
public TaskWrapper(T task, long delayInMillis, long key) {
this.task = task;
this.delayInMillis = delayInMillis;
this.key = key;
}
// getter, setters, and so on
public boolean equals(Object o) {
if (o == null || !(o instanceof TaskWrapper)) return false;
return key == ((TaskWrapper) o).key;
}
}
A queue decorator adds the 'set' like behaviour. A queue doesn't have 'contains' method, so I take an additional Set to record the objects that are actually enqued. All methods that change the queue will be implemented to keep the consistency between the internal queue and the set. This quick draft is not thread safe and shows just the add
method.
public SetQueue<TaskWrapper> implements Queue<T> {
private Queue<TaskWrapper> queue;
private Set<TaskWrapper> set = new HashSet<TaskWrapper>();
public SetQueue(Queue<TaskWrapper> queue) {
this.queue = queue;
}
// just to demonstrate the idea
public boolean add(TaskWrapper<?> task) {
if (set.contains(task)
return false;
boolean result = queue.add(task);
if (result)
set.add(task);
return result;
}
(may be full of bugs, I don't have an IDE at hand. It's just a draft)