Search code examples
javajava-streampriority-queue

How to customize PriorityQueue.stream().foreach to iterate in priority order


I have a class with PriorityQueue field inside:

public class MyClass<T>{
    Queue<T> queue = new PriorityQueue<>();

I want somehow get a stream from MyClass and use foreach and want the sequence behave in priority order of my PriorityQueue. The easiest way is to override stream() method:

@Override
public Stream stream() {
    return queue.stream();
}

but this will not expose the queue element in priority order. So the question is: how to make foreach stream method behave like:

    while(!queue.isEmpty()) 
        queue.poll();

Solution

  • You could use Stream::generate and Queue::poll method to get create a Stream with elements from PriorityQueue with keeping their order:

    @Override
    public Stream<T> stream() {
        return Stream.generate(queue::poll);
    }
    

    However this might be dangerous because Stream::generate will be invoking poll constantly so it is potentially an inifinite Stream. Therfore using Stream::limit with the queue size should be considered :

    @Override
    public Stream<T> stream() {
        return Stream.generate(queue::poll)
            .limit(queue.size());
    }
    

    Or you could simply return sorted stream :

    @Override
    public Stream<T> stream() {
        return queue.stream()
                .sorted(comparator);
    }
    

    where comparator is your comparator.

    In Java 9 you could use Stream::takeWhile with predicate that rejects nulls. As Queue::poll will return null when queue is empty - the resulting Stream will contain elements from the queue in their order (this is alternative to using limit as described in the first solution) :

    @Override
    public Stream<T> stream() {
        return Stream.generate(queue::poll)
                .takeWhile(Objects::nonNull);
    }