001/* 002 * JDrupes Builder 003 * Copyright (C) 2026 Michael N. Lipp 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <https://www.gnu.org/licenses/>. 017 */ 018 019package org.jdrupes.builder.core; 020 021import java.util.Collection; 022import java.util.Iterator; 023import java.util.Spliterators; 024import java.util.function.Consumer; 025import java.util.function.Supplier; 026import java.util.stream.Stream; 027import java.util.stream.StreamSupport; 028 029/// A stream of elements whose backing collection is obtained lazily from 030/// a supplier when the stream is first consumed. 031/// 032/// @param <T> the element type 033/// 034public final class LazyCollectionStream<T> 035 extends Spliterators.AbstractSpliterator<T> { 036 037 private final Supplier<Collection<T>> supplier; 038 private Iterator<T> theIterator; 039 040 private LazyCollectionStream(Supplier<Collection<T>> supplier) { 041 super(Long.MAX_VALUE, IMMUTABLE); 042 this.supplier = supplier; 043 } 044 045 private Iterator<T> iterator() { 046 if (theIterator == null) { 047 theIterator = supplier.get().iterator(); 048 } 049 return theIterator; 050 } 051 052 @Override 053 public void forEachRemaining(Consumer<? super T> action) { 054 iterator().forEachRemaining(action); 055 } 056 057 @Override 058 public boolean tryAdvance(Consumer<? super T> action) { 059 if (!iterator().hasNext()) { 060 return false; 061 } 062 action.accept(iterator().next()); 063 return true; 064 } 065 066 /// Creates a stream backed by a collection supplied lazily by the 067 /// given supplier. The supplier is invoked only when the stream is 068 /// first consumed. 069 /// 070 /// @param <T> the element type 071 /// @param supplier supplies the collection 072 /// @return the stream 073 /// 074 @SuppressWarnings("PMD.ShortMethodName") 075 public static <T> Stream<T> of(Supplier<Collection<T>> supplier) { 076 return StreamSupport.stream( 077 new LazyCollectionStream<>(supplier), false); 078 } 079}