All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aksw.commons.collections.utils.StreamUtils Maven / Gradle / Ivy

There is a newer version: 0.9.9
Show newest version
package org.aksw.commons.collections.utils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.aksw.commons.collections.IteratorUtils;
import org.aksw.commons.lambda.throwing.ThrowingBiConsumer;
import org.aksw.commons.lambda.throwing.ThrowingFunction;

import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Streams;

public class StreamUtils {

    /**
     * Create a single-use {@link Iterable} from a stream. Allows for easier use of Streams in
     * for-loops:
     *
     * 
{@code
     *   Stream stream = ...;
     *   for (T item : StreamUtils.iterableOf(stream)) {
     *   }
     * }
* * @param * @param stream * @return */ public static Iterable iterable(Stream stream) { Iterable result = () -> stream.iterator(); return result; } public static T expectOneItem(Stream stream) { try { return IteratorUtils.expectOneItem(stream.iterator()); } finally { stream.close(); } } public static T expectZeroOrOneItems(Stream stream) { try { return IteratorUtils.expectZeroOrOneItems(stream.iterator()); } finally { stream.close(); } } /** * Note we could implement another version where each batch's List is lazy loaded from the stream - * but this would probably require complete consumption of each batch in order * * @param stream * @param batchSize * @return */ public static Stream> mapToBatch(Stream stream, int batchSize) { Iterator baseIt = stream.iterator(); Iterator> it = new AbstractIterator>() { @Override protected List computeNext() { List items = new ArrayList<>(batchSize); for(int i = 0; baseIt.hasNext() && i < batchSize; ++i) { T item = baseIt.next(); items.add(item); } List r = items.isEmpty() ? endOfData() : items; return r; } }; Iterable> tmp = () -> it; Stream> result = Streams.stream(tmp); result.onClose(() -> stream.close()); return result; } // public static Stream stream(Iterator it) { // Iterable i = () -> it; // return stream(i); // } // // public static Stream stream(Iterable i) { // Stream result = StreamSupport.stream(i.spliterator(), false); // return result; // } /** * Creates a new stream which upon reaching its end performs and action. * It concatenates the original stream with one having a single item * that is filtered out again. The action is run as- part of the filter. * * @param stream * @param runnable * @return */ public static Stream appendAction(Stream stream, Runnable runnable) { Stream result = Stream.concat( stream, Stream .of((T)null) .filter(x -> { runnable.run(); return false; }) ); return result; } // TODO Add to StreamUtils public static Stream stream(BiConsumer> fn, S baseSolution) { List result = new ArrayList<>(); fn.accept(baseSolution, (item) -> result.add(item)); return result.stream(); } /** * Creates a stream over a resource via an enumerable. * The resource is initialized lazily once the first item is read from the stream. * The returned stream should be used in a try-with-resources block in order * to close the underlying resource. * * @param The record type (e.g. an array of Strings) * @param The resource type (e.g. a java.sql.Connection) * @param An enumerable (e.g. a java.sql.ResultSet) * @param resourceSupplier * @param toEnumerable * @param nextRecord * @param closer * @return */ public static Stream fromEnumerableResource( Callable resourceSupplier, ThrowingFunction toEnumerable, ThrowingFunction nextRecord, BiPredicate hasEnded, ThrowingBiConsumer closer) { IteratorOverEnumerable it = new IteratorOverEnumerable<>(resourceSupplier, toEnumerable, nextRecord, hasEnded, closer); Stream result = Streams.stream(it).onClose(it::close); return result; } public static class IteratorOverEnumerable extends AbstractIterator implements AutoCloseable { protected Callable resourceSupplier; protected ThrowingFunction toEnumerable; protected ThrowingFunction nextRecord; protected BiPredicate hasEnded; protected ThrowingBiConsumer closer; protected boolean isClosed = false; protected R resource; protected E enumerable; public IteratorOverEnumerable( Callable resourceSupplier, ThrowingFunction toEnumerable, ThrowingFunction nextRecord, BiPredicate hasEnded, ThrowingBiConsumer closer) { this.resourceSupplier = resourceSupplier; this.toEnumerable = toEnumerable; this.nextRecord = nextRecord; this.hasEnded = hasEnded; this.closer = closer; } @Override protected T computeNext() { if (isClosed) { throw new IllegalStateException("already closed"); } if (enumerable == null) { try { if (resource == null) { resource = resourceSupplier.call(); } enumerable = toEnumerable.apply(resource); } catch (Exception e) { throw new RuntimeException(e); } } T result; try { result = nextRecord.apply(enumerable); } catch (Exception e) { throw new RuntimeException(e); } boolean isDone = hasEnded.test(result, enumerable); if (isDone) { result = endOfData(); } return result; } @Override public void close() { isClosed = true; try { if (resource != null) { closer.accept(resource, enumerable); } } catch (Exception e) { throw new RuntimeException(e); } } } public static Stream viaList(Stream in, Consumer> consumer) { List list; try (Stream tmp = in) { list = tmp.collect(Collectors.toList()); } if (consumer != null) { consumer.accept(list); } return list.stream(); } public static Stream println(Stream in) { return viaList(in, System.out::println); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy