/* * Copyright 2016-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.util; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import java.util.Comparator; import java.util.Iterator; import java.util.Optional; import java.util.Spliterators; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; import java.util.stream.StreamSupport; /** * Java 8 streams with "rich" API (convenience methods). * * <p>The default Java 8 Stream implementation is deliberately spartan in API methods in order to * avoid dependencies on Collections, and to focus on parallelism. This wrapper adds common * operations to the Stream API, mostly inspired by Guava's {@code FluentIterable}. * * @param <T> the type of the stream elements. */ public interface RichStream<T> extends Stream<T> { // Static methods static <T> RichStream<T> empty() { return new RichStreamImpl<>(Stream.empty()); } static <T> RichStream<T> of(T value) { return new RichStreamImpl<>(Stream.of(value)); } @SafeVarargs static <T> RichStream<T> of(T... values) { return new RichStreamImpl<>(Stream.of(values)); } static <T> RichStream<T> from(Iterable<T> iterable) { return new RichStreamImpl<>(StreamSupport.stream(iterable.spliterator(), false)); } static <T> RichStream<T> from(Iterator<T> iterator) { return new RichStreamImpl<>( StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false)); } static <T> RichStream<T> from(Optional<? extends T> optional) { return optional.isPresent() ? of(optional.get()) : empty(); } static <T> RichStream<T> fromSupplierOfIterable(Supplier<? extends Iterable<T>> supplier) { return new RichStreamImpl<>(StreamSupport.stream(() -> supplier.get().spliterator(), 0, false)); } static <T> RichStream<T> from(Stream<T> stream) { if (stream instanceof RichStream) { return (RichStream<T>) stream; } else { return new RichStreamImpl<>(stream); } } // Convenience functions that can be implemented with existing primitives. /** * @param other Stream to concatenate into the current one. * @return Stream containing the elements of the current stream followed by that of the given * stream. */ default RichStream<T> concat(Stream<T> other) { return new RichStreamImpl<>(Stream.concat(this, other)); } /** * Filter stream elements, returning only those that is an instance of the given class. * * @param cls Class instance of the class to cast to. * @param <U> Class to cast to. * @return Filtered stream of instances of {@code cls}. */ @SuppressWarnings("unchecked") default <U> RichStream<U> filter(Class<U> cls) { return (RichStream<U>) filter(cls::isInstance); } default ImmutableList<T> toImmutableList() { return collect(MoreCollectors.toImmutableList()); } default ImmutableSet<T> toImmutableSet() { return collect(MoreCollectors.toImmutableSet()); } default ImmutableSortedSet<T> toImmutableSortedSet(Comparator<? super T> ordering) { return collect(MoreCollectors.toImmutableSortedSet(ordering)); } default Iterable<T> toOnceIterable() { return this::iterator; } // More specific return types for Stream methods that return Streams. @Override RichStream<T> filter(Predicate<? super T> predicate); @Override <R> RichStream<R> map(Function<? super T, ? extends R> mapper); @Override <R> RichStream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper); @Override RichStream<T> distinct(); @Override RichStream<T> sorted(); @Override RichStream<T> sorted(Comparator<? super T> comparator); @Override RichStream<T> peek(Consumer<? super T> action); @Override RichStream<T> limit(long maxSize); @Override RichStream<T> skip(long n); @Override RichStream<T> sequential(); @Override RichStream<T> parallel(); @Override RichStream<T> unordered(); @Override RichStream<T> onClose(Runnable closeHandler); }