Допустим, у меня очередь, и я хочу ее исчерпать. Я бы сделал что-то вроде
void emptyQueue(Queue<T> q) {
T i;
while ((i = q.poll()) != null)
consume(i);
}
но это кажется архаичным методом.
Хотелось бы чего-то более похожего на метод forEach. Он, конечно, присутствует - Queue является Collection - но он перебирает элементы, а не потребляет их.
В идеале мне бы понравился метод pollEach на Queue, но я не могу найти ничего подходящего.
Как написать такой код?
@daniu, который не удаляет элементы из очереди по мере их использования.
вы можете изменить while на: for(T ti= null; (i = queue.poll()) != null; ){...}, что может быть немного лучше, потому что переменная i доступна только внутри области видимости for
Если ваша очередь наследуется от AbstractQueue, вы можете просто использовать метод clear().




Вы можете использовать собственный генератор, который вызывает poll() в очереди:
Stream.generate( () -> q.poll() )
.takeWhile(Objects::nonNull) //Note that this is only available in java 9
.forEach(i -> consume(i));
Этот метод также является примером контроля над тем, что проходит поток. Вы можете управлять такими вещами, как блокировка и т. д. Шаг takeWhile в этом случае просто показывает, как можно определить конец данных.
Мне очень нравится это решение, вы можете сократить () -> q.poll() до q::poll, а также i -> consume(i) до this::consume (при условии, что consume является членом экземпляра класса`)
Обратите внимание, что Stream.generate создает поток неупорядоченный, поэтому семантически это неправильное решение (или, по крайней мере, не идентичное исходному коду), даже если происходит обработка элементов в правильном порядке при последовательном выполнении. И все равно преимущества перед «архаичной» петлей нет…
Вы действительно добавляете потребителя к
forEach...q.forEach(this::consume);должен быть эквивалентен вашему коду.