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

com.aol.cyclops.sequence.SequenceMImpl Maven / Gradle / Ivy

There is a newer version: 7.3.1
Show newest version
package com.aol.cyclops.sequence;

import java.io.BufferedReader;
import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.Spliterator;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.stream.BaseStream;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;

import org.jooq.lambda.Seq;
import org.jooq.lambda.tuple.Tuple;
import org.jooq.lambda.tuple.Tuple2;
import org.jooq.lambda.tuple.Tuple3;
import org.jooq.lambda.tuple.Tuple4;
import org.reactivestreams.Subscriber;

import com.aol.cyclops.internal.AsGenericMonad;
import com.aol.cyclops.lambda.monads.ComprehenderSelector;
import com.aol.cyclops.monad.AnyM;
import com.aol.cyclops.sequence.future.FutureOperations;
import com.aol.cyclops.sequence.reactivestreams.ReactiveStreamsLoader;
import com.aol.cyclops.sequence.spliterators.ReversableSpliterator;
import com.aol.cyclops.sequence.streamable.AsStreamable;
import com.aol.cyclops.sequence.streamable.Streamable;
import com.aol.cyclops.streams.StreamUtils;



public class SequenceMImpl implements Unwrapable, SequenceM, Iterable{
	private final Seq stream;
	private final Optional reversable;
	
	public SequenceMImpl(Stream stream){
		this.stream = Seq.seq(stream);
		this.reversable = Optional.empty();
		
	}
	
	public SequenceMImpl(Stream stream,ReversableSpliterator rev){
		this.stream = Seq.seq(stream);
		this.reversable = Optional.of(rev);
		
	}
	
	
	public final  R unwrap(){
		return (R)stream;
	}

	/**
	 * join / flatten one level of a nested hierarchy
	 * 
	 * 
	 * {@code 
	 *  assertThat(SequenceM.of(Arrays.asList(1,2)).flatten().toList().size(),equalTo(asList(1,  2).size()));		
	 *  
	 *  // or more advanced example 
	 *  
	 *  AnyM> applied =anyM(Optional.of(2))
			 							.simpleFilter(anyM(Streamable.of( (Integer a)->a>5 ,(Integer a) -> a<3)));
	
	     assertThat(applied.toSequence().flatten().toList(),equalTo(Arrays.asList(2)));
	 * 
	 * }
	 * 
	 * 
* * @return Flattened / joined one level */ public final SequenceM flatten(){ return StreamUtils.flatten(stream); } /** * Type safe unwrap * *
	 * {@code 
	 * Stream stream = anyM("hello","world").asSequence().unwrapStream();
		assertThat(stream.collect(Collectors.toList()),equalTo(Arrays.asList("hello","world")));
	 * }
	 * 
* @return Stream with current wrapped values */ public final Stream unwrapStream(){ return stream; } /** * Type safe unwrap *
	 * {@code 
	 * Optional> stream = anyM("hello","world")
											.asSequence()
											.unwrapOptional();
		assertThat(stream.get(),equalTo(Arrays.asList("hello","world")));
	 * }
	 * 
	 * 
* @return */ public final Optional> toOptional(){ return StreamUtils.streamToOptional(stream); } /** *
	 * {@code 
	 * CompletableFuture> cf = anyM("hello","world")
											.asSequence()
											.unwrapCompletableFuture();
		assertThat(cf.join(),equalTo(Arrays.asList("hello","world")));
	 * }
	 * 
* @return */ public final CompletableFuture> toCompletableFuture(){ return StreamUtils.streamToCompletableFuture(stream); } /** * Convert to a Stream with the values repeated specified times * *
	 * {@code 
	 * 		assertThat(anyM(Stream.of(1,2,2)).asSequence()
											.cycle(3).collect(Collectors.toList()),
											equalTo(Arrays.asList(1,2,2,1,2,2,1,2,2)));

	 * 
	 * }
	 * 
* @param times * Times values should be repeated within a Stream * @return Stream with values repeated */ public final SequenceM cycle(int times) { return StreamUtils.sequenceM(StreamUtils.cycle(times,AsStreamable.fromStream(stream)),reversable); } /** * Convert to a Stream with the values infinitely cycled * *
	 * {@code 
	 *   assertEquals(asList(1, 1, 1, 1, 1,1),of(1).cycle().limit(6).toList());
	 *   }
	 * 
* * @return Stream with values repeated */ public final SequenceM cycle() { return StreamUtils.sequenceM(StreamUtils.cycle(stream),reversable); } /** * Duplicate a Stream, buffers intermediate values, leaders may change positions so a limit * can be safely applied to the leading stream. Not thread-safe. *
	 * {@code 
	 *  Tuple2, SequenceM> copies =of(1,2,3,4,5,6).duplicate();
		 assertTrue(copies.v1.anyMatch(i->i==2));
		 assertTrue(copies.v2.anyMatch(i->i==2));
	 * 
	 * }
	 * 
* * @return duplicated stream */ public final Tuple2,SequenceM> duplicateSequence(){ Tuple2,Stream> tuple = StreamUtils.duplicate(stream); return tuple.map1(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))) .map2(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))); } /** * Triplicates a Stream * Buffers intermediate values, leaders may change positions so a limit * can be safely applied to the leading stream. Not thread-safe. *
	 * {@code 
	 * 	Tuple3>,SequenceM>,SequenceM>> Tuple3 = sequence.triplicate();
	
	 * }
	 * 
*/ @SuppressWarnings("unchecked") public final Tuple3,SequenceM,SequenceM> triplicate(){ Tuple3,Stream,Stream> tuple = StreamUtils.triplicate(stream); return tuple.map1(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))) .map2(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))) .map3(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))); } /** * Makes four copies of a Stream * Buffers intermediate values, leaders may change positions so a limit * can be safely applied to the leading stream. Not thread-safe. * *
	 * {@code
	 * 
	 * 		Tuple4>,SequenceM>,SequenceM>,SequenceM>> quad = sequence.quadruplicate();

	 * }
	 * 
* @return */ @SuppressWarnings("unchecked") public final Tuple4,SequenceM,SequenceM,SequenceM> quadruplicate(){ Tuple4,Stream,Stream,Stream> tuple = StreamUtils.quadruplicate(stream); return tuple.map1(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))) .map2(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))) .map3(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))) .map4(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))); } /** * Split a Stream at it's head (similar to headAndTail) *
	 * {@code 
	 * SequenceM.of(1,2,3).splitAtHead()
	 * 
	 *  //Optional[1], SequenceM[2,3]
	 * }
	 * 
	 * 
* */ @SuppressWarnings({ "unchecked", "rawtypes" }) public final Tuple2,SequenceM> splitSequenceAtHead(){ Tuple2,SequenceM> Tuple2 = splitAt(1); return new Tuple2(Tuple2.v1.toOptional() .flatMap( l-> l.size()>0 ? Optional.of(l.get(0)) : Optional.empty() ) ,Tuple2.v2); } /** * Split at supplied location *
	 * {@code 
	 * SequenceM.of(1,2,3).splitAt(1)
	 * 
	 *  //SequenceM[1], SequenceM[2,3]
	 * }
	 * 
	 * 
*/ public final Tuple2,SequenceM> splitAt(int where){ return StreamUtils.splitAt(stream, where) .map1(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))) .map2(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))); } /** * Split stream at point where predicate no longer holds *
	 * {@code
	 *   SequenceM.of(1, 2, 3, 4, 5, 6).splitBy(i->i<4)
	 *   
	 *   //SequenceM[1,2,3] SequenceM[4,5,6]
	 * }
	 * 
*/ public final Tuple2,SequenceM> splitBy(Predicate splitter){ return StreamUtils.splitBy(stream, splitter) .map1(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))) .map2(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))); } /** * Partition a Stream into two one a per element basis, based on predicate's boolean value *
	 * {@code 
	 *  SequenceM.of(1, 2, 3, 4, 5, 6).partition(i -> i % 2 != 0) 
	 *  
	 *  //SequenceM[1,3,5], SequenceM[2,4,6]
	 * }
	 *
	 * 
*/ public final Tuple2,SequenceM> partitionSequence(Predicate splitter){ return StreamUtils.partition(stream, splitter) .map1(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))) .map2(s->StreamUtils.sequenceM(s,reversable.map(r->r.copy()))); } /** * Convert to a Stream with the result of a reduction operation repeated * specified times * *
	 * {@code 
	 *   		List list = AsGenericMonad,asStreamUtils.sequenceM(Stream.of(1,2,2))
	 * 										.cycle(Reducers.toCountInt(),3)
	 * 										.collect(Collectors.toList());
	 * 	//is asList(3,3,3);
	 *   }
	 * 
* * @param m * Monoid to be used in reduction * @param times * Number of times value should be repeated * @return Stream with reduced values repeated */ public final SequenceM cycle(Monoid m, int times) { return StreamUtils.sequenceM(StreamUtils.cycle(times,Streamable.of(m.reduce(stream))),reversable); } /** * * Convert to a Stream, repeating the resulting structure specified times * and lifting all values to the specified Monad type * *
	 * {
	 * 	@code
	 * 	List<Optional<Integer>> list = StreamUtils.sequenceM(Stream.of(1, 2)).cycle(Optional.class,
	 * 			2).toList();
	 * 
	 * 	// is asList(Optional.of(1),Optional.of(2),Optional.of(1),Optional.of(2) ));
	 * 
	 * }
	 * 
* * * * @param monadC * class type * @param times * @return */ public final SequenceM cycle(Class monadC, int times) { return (SequenceMImpl)cycle(times).map(r -> new ComprehenderSelector().selectComprehender(monadC).of(r)); } /** * Repeat in a Stream while specified predicate holds * *
	 * {@code
	 * count =0;
		assertThat(anyM(Stream.of(1,2,2)).asSequence()
											.cycleWhile(next -> count++<6)
											.collect(Collectors.toList()),equalTo(Arrays.asList(1,2,2,1,2,2)));
	 * }
	 * 
* * @param predicate * repeat while true * @return Repeating Stream */ public final SequenceM cycleWhile(Predicate predicate) { return StreamUtils.sequenceM(StreamUtils.cycle(stream),reversable).limitWhile(predicate); } /** * Repeat in a Stream until specified predicate holds *
	 * {@code 
	 * 	count =0;
		assertThat(anyM(Stream.of(1,2,2)).asSequence()
											.cycleUntil(next -> count++>6)
											.collect(Collectors.toList()),equalTo(Arrays.asList(1,2,2,1,2,2,1)));

	 * 
	 * }
	 * 
	 * 
	 * @param predicate
	 *            repeat while true
	 * @return Repeating Stream
	 */
	public final SequenceM cycleUntil(Predicate predicate) {
		return StreamUtils.sequenceM(StreamUtils.cycle(stream),reversable).limitWhile(predicate.negate());
	}
	/**
	 * Zip 2 streams into one
	 * 
	 * 
	 * {@code 
	 * List> list = of(1, 2).zip(of("a", "b", "c", "d")).toList();
       // [[1,"a"],[2,"b"]]
		 } 
	 * 
* */ public final SequenceM> zip(Stream second){ return zipStream(second,(a,b)->new Tuple2<>(a,b)); } /** * zip 3 Streams into one *
	 * {@code 
	 * List> list =
				of(1,2,3,4,5,6).zip3(of(100,200,300,400),of('a','b','c'))
											.collect(Collectors.toList());
	 * 
	 * //[[1,100,'a'],[2,200,'b'],[3,300,'c']]
	 * }
	 * 
	 *
*/ public final SequenceM> zip3(Stream second,Stream third){ return zip(second).zipStream(third).map(p -> new Tuple3(p.v1().v1(),p.v1().v2(),p.v2())); } /** * zip 4 Streams into 1 * *
	 * {@code 
	 * List> list =
				of(1,2,3,4,5,6).zip4(of(100,200,300,400),of('a','b','c'),of("hello","world"))
												.collect(Collectors.toList());
			
	 * }
	 *  //[[1,100,'a',"hello"],[2,200,'b',"world"]]
	 * 
*/ public final SequenceM> zip4(Stream second,Stream third,Stream fourth){ return zip3(second,third).zipStream(fourth).map(t -> new Tuple4(t.v1().v1(), t.v1().v2(),t.v1().v3(),t.v2())); } /** * Add an index to the current Stream * *
	 * {@code 
	 * assertEquals(asList(new Tuple2("a", 0L), new Tuple2("b", 1L)), of("a", "b").zipWithIndex().toList());
	 * }
	 * 
*/ public final SequenceM> zipWithIndex(){ return zipStream(LongStream.iterate(0, i->i+1),(a,b)->new Tuple2<>(a,b)); } /** * Generic zip function. E.g. Zipping a Stream and an Optional * *
	 * {
	 * 	@code
	 * 	Stream<List<Integer>> zipped = asStreamUtils.sequenceM(Stream.of(1, 2, 3)).zip(
	 * 			asStreamUtils.sequenceM(Optional.of(2)), (a, b) -> Arrays.asList(a, b));
	 * 	// [[1,2]]
	 * }
	 * 
* * @param second * Monad to zip with * @param zipper * Zipping function * @return Stream zipping two Monads */ public final SequenceM zipSequence(SequenceM second, BiFunction zipper) { return StreamUtils.sequenceM(StreamUtils.zipSequence(stream,second, zipper),Optional.empty()); } /** * Zip this SequenceM against any monad type. * *
	 * {@code
	 * Stream> zipped = anyM(Stream.of(1,2,3))
										.asSequence()
										.zip(anyM(Optional.of(2)), 
											(a,b) -> Arrays.asList(a,b)).toStream();
		
		
		List zip = zipped.collect(Collectors.toList()).get(0);
		assertThat(zip.get(0),equalTo(1));
		assertThat(zip.get(1),equalTo(2));
	 * }
	 * 
* */ public final SequenceM zip(AnyM second, BiFunction zipper) { return zipSequence(second.toSequence(), zipper); } /** * Zip this Monad with a Stream * *
	 * {
	 * 	@code
	 * 	Stream<List<Integer>> zipped = asStreamUtils.sequenceM(Stream.of(1, 2, 3)).zip(
	 * 			Stream.of(2, 3, 4), (a, b) -> Arrays.asList(a, b));
	 * 
	 * 	// [[1,2][2,3][3,4]]
	 * }
	 * 
* * @param second * Stream to zip with * @param zipper * Zip funciton * @return This monad zipped with a Stream */ public final SequenceM zipStream(BaseStream> second, BiFunction zipper) { return StreamUtils.sequenceM(StreamUtils.zipStream(stream,second, zipper),Optional.empty()); } /** * Create a sliding view over this Sequence * *
	 * {@code 
	 * List> list = anyM(Stream.of(1,2,3,4,5,6))
									.asSequence()
									.sliding(2)
									.collect(Collectors.toList());
		
	
		assertThat(list.get(0),hasItems(1,2));
		assertThat(list.get(1),hasItems(2,3));
	 * 
	 * }
	 * 
	 * 
* @param windowSize * Size of sliding window * @return SequenceM with sliding view */ public final SequenceM> sliding(int windowSize) { return StreamUtils.sequenceM(StreamUtils.sliding(stream,windowSize),reversable); } /** * Create a sliding view over this Sequence *
	 * {@code 
	 * List> list = anyM(Stream.of(1,2,3,4,5,6))
									.asSequence()
									.sliding(3,2)
									.collect(Collectors.toList());
		
	
		assertThat(list.get(0),hasItems(1,2,3));
		assertThat(list.get(1),hasItems(3,4,5));
	 * 
	 * }
	 * 
	 * 
* * @param windowSize number of elements in each batch * @param increment for each window * @return SequenceM with sliding view */ public final SequenceM> sliding(int windowSize,int increment) { return StreamUtils.sequenceM(StreamUtils.sliding(stream,windowSize,increment),reversable); } /** * Group elements in a Stream * *
	 * {
	 * 	@code
	 * 	List<List<Integer>> list = StreamUtils.sequenceM(Stream.of(1, 2, 3, 4, 5, 6)).grouped(3)
	 * 			.collect(Collectors.toList());
	 * 
	 * 	assertThat(list.get(0), hasItems(1, 2, 3));
	 * 	assertThat(list.get(1), hasItems(4, 5, 6));
	 * 
	 * }
	 * 
* * @param groupSize * Size of each Group * @return Stream with elements grouped by size */ public final SequenceM> grouped(int groupSize) { return StreamUtils.sequenceM(StreamUtils.batchBySize(stream,groupSize),reversable); } /** * Use classifier function to group elements in this Sequence into a Map *
	 * {@code 
	 * Map> map1 =of(1, 2, 3, 4).groupBy(i -> i % 2);
		        assertEquals(asList(2, 4), map1.get(0));
		        assertEquals(asList(1, 3), map1.get(1));
		        assertEquals(2, map1.size());
	 * 
	 * }
	 * 
	 * 
*/ public final Map> groupBy(Function classifier) { return collect(Collectors.groupingBy(classifier)); } /* * Return the distinct Stream of elements * *
{@code List list =
	 *        anyM(Optional.of(Arrays.asList(1,2,2,2,5,6)))
	 *           .,Integer>toSequence() .distinct()
	 *				 .collect(Collectors.toList()); 
	 * }
	 *
*/ public final SequenceM distinct() { return StreamUtils.sequenceM(stream.distinct(),reversable); } /** * Scan left using supplied Monoid * *
	 * {@code  
	 * 
	 * 	assertEquals(asList("", "a", "ab", "abc"),StreamUtils.sequenceM(Stream.of("a", "b", "c")).scanLeft(Reducers.toString("")).toList());
	 *         
	 *         }
	 * 
* * @param monoid * @return */ public final SequenceM scanLeft(Monoid monoid) { return StreamUtils.sequenceM(StreamUtils.scanLeft(stream,monoid),reversable); } /** * Scan left *
	 * {@code 
	 *  assertThat(of("a", "b", "c").scanLeft("", String::concat).toList().size(),
        		is(4));
	 * }
	 * 
*/ public final SequenceM scanLeft(U seed, BiFunction function) { return StreamUtils.sequenceM(stream.scanLeft(seed, function),reversable); } /** * Scan right *
	 * {@code 
	 * assertThat(of("a", "b", "c").scanRight(Monoid.of("", String::concat)).toList().size(),
            is(asList("", "c", "bc", "abc").size()));
	 * }
	 * 
*/ public final SequenceM scanRight(Monoid monoid) { return StreamUtils.sequenceM(reverse().scanLeft(monoid.zero(), (u, t) -> monoid.combiner().apply(t, u)),reversable); } /** * Scan right * *
	 * {@code 
	 * assertThat(of("a", "ab", "abc").map(str->str.length()).scanRight(0, (t, u) -> u + t).toList().size(),
            is(asList(0, 3, 5, 6).size()));
	 * 
	 * }
	 * 
*/ public final SequenceM scanRight(U identity,BiFunction combiner){ return StreamUtils.sequenceM(StreamUtils.scanRight(stream,identity,combiner),reversable); } /** *
	 * {@code assertThat(SequenceM.of(4,3,6,7)).sorted().toList(),equalTo(Arrays.asList(3,4,6,7))); }
	 * 
* */ public final SequenceM sorted() { return StreamUtils.sequenceM(stream.sorted(),reversable); } /** *
	 * {@code 
	 * 	assertThat(anyM(Stream.of(4,3,6,7)).asSequence().sorted((a,b) -> b-a).toList(),equalTo(Arrays.asList(7,6,4,3)));
	 * }
	 * 
* @param c * Compartor to sort with * @return Sorted Monad */ public final SequenceM sorted(Comparator c) { return StreamUtils.sequenceM(stream.sorted(c),reversable); } /** *
	 * {@code assertThat(anyM(Stream.of(4,3,6,7)).asSequence().skip(2).toList(),equalTo(Arrays.asList(6,7))); }
	 * 
* * * @param num * Number of elemenets to skip * @return Monad converted to Stream with specified number of elements * skipped */ public final SequenceM skip(long num) { return StreamUtils.sequenceM( stream.skip(num),reversable); } /** * * *
	 * {@code
	 * assertThat(anyM(Stream.of(4,3,6,7)).asSequence().sorted().skipWhile(i->i<6).toList(),equalTo(Arrays.asList(6,7)));
	 * }
	 * 
* * @param p * Predicate to skip while true * @return Monad converted to Stream with elements skipped while predicate * holds */ public final SequenceM skipWhile(Predicate p) { return StreamUtils.sequenceM(StreamUtils.skipWhile(stream, p),reversable); } /** * * *
	 * {@code assertThat(anyM(Stream.of(4,3,6,7)).asSequence().skipUntil(i->i==6).toList(),equalTo(Arrays.asList(6,7)));}
	 * 
* * * @param p * Predicate to skip until true * @return Monad converted to Stream with elements skipped until predicate * holds */ public final SequenceM skipUntil(Predicate p) { return StreamUtils.sequenceM(StreamUtils.skipUntil(stream,p),reversable); } /** * * *
	 * {@code assertThat(anyM(Stream.of(4,3,6,7)).asSequence().limit(2).toList(),equalTo(Arrays.asList(4,3)));}
	 * 
* * @param num * Limit element size to num * @return Monad converted to Stream with elements up to num */ public final SequenceM limit(long num) { return StreamUtils.sequenceM(stream.limit(num),reversable); } /** * * *
	 * {@code assertThat(anyM(Stream.of(4,3,6,7)).asSequence().sorted().limitWhile(i->i<6).toList(),equalTo(Arrays.asList(3,4)));}
	 * 
* * @param p * Limit while predicate is true * @return Monad converted to Stream with limited elements */ public final SequenceM limitWhile(Predicate p) { return StreamUtils.sequenceM(StreamUtils.limitWhile(stream,p),reversable); } /** * * *
	 * {@code assertThat(anyM(Stream.of(4,3,6,7)).limitUntil(i->i==6).toList(),equalTo(Arrays.asList(4,3))); }
	 * 
* * @param p * Limit until predicate is true * @return Monad converted to Stream with limited elements */ public final SequenceM limitUntil(Predicate p) { return StreamUtils.sequenceM(StreamUtils.limitUntil(stream,p),reversable); } /** * @return does nothing - returns this * */ public final SequenceM parallel(){ return this; } /** * True if predicate matches all elements when Monad converted to a Stream *
	 * {@code 
	 * assertThat(of(1,2,3,4,5).allMatch(it-> it>0 && it <6),equalTo(true));
	 * }
	 * 
* @param c Predicate to check if all match */ public final boolean allMatch(Predicate c) { return stream.allMatch(c); } /** * True if a single element matches when Monad converted to a Stream *
	 * {@code 
	 * assertThat(of(1,2,3,4,5).anyMatch(it-> it.equals(3)),equalTo(true));
	 * }
	 * 
* @param c Predicate to check if any match */ public final boolean anyMatch(Predicate c) { return stream.anyMatch(c); } /** * Check that there are specified number of matches of predicate in the Stream * *
	 * {@code 
	 *  assertTrue(SequenceM.of(1,2,3,5,6,7).xMatch(3, i-> i>4 ));
	 * }
	 * 
* */ public boolean xMatch(int num, Predicate c) { return stream.filter(t -> c.test(t)) .collect(Collectors.counting()) == num; } /* *
	 * {@code 
	 * assertThat(of(1,2,3,4,5).noneMatch(it-> it==5000),equalTo(true));
	 * 
	 * }
	 * 
*/ public final boolean noneMatch(Predicate c) { return stream.allMatch(c.negate()); } /** *
	 * {@code
	 *  assertEquals("123".length(),of(1, 2, 3).join().length());
	 * }
	 * 
* * @return Stream as concatenated String */ public final String join(){ return StreamUtils.join(stream,""); } /** *
	 * {@code
	 * assertEquals("1, 2, 3".length(), of(1, 2, 3).join(", ").length());
	 * }
	 * 
* @return Stream as concatenated String */ public final String join(String sep){ return StreamUtils.join(stream,sep); } /** *
	 * {@code 
	 * assertEquals("^1|2|3$".length(), of(1, 2, 3).join("|", "^", "$").length());
	 * }
	 * 
* @return Stream as concatenated String */ public final String join(String sep,String start, String end){ return StreamUtils.join(stream, sep,start, end); } /** * Extract the minimum as determined by supplied function * */ public final > Optional minBy(Function function){ return StreamUtils.minBy(stream,function); } /* (non-Javadoc) * @see java.util.stream.Stream#min(java.util.Comparator) */ public final Optional min(Comparator comparator){ return StreamUtils.min(stream,comparator); } /** * Extract the maximum as determined by the supplied function * */ public final > Optional maxBy(Function f){ return StreamUtils.maxBy(stream,f); } /* (non-Javadoc) * @see java.util.stream.Stream#max(java.util.Comparator) */ public final Optional max(Comparator comparator){ return StreamUtils.max(stream,comparator); } /** * extract head and tail together, where head is expected to be present * *
	 * {@code
	 *  SequenceM helloWorld = SequenceM.of("hello","world","last");
		HeadAndTail headAndTail = helloWorld.headAndTail();
		 String head = headAndTail.head();
		 assertThat(head,equalTo("hello"));
		
		SequenceM tail =  headAndTail.tail();
		assertThat(tail.headAndTail().head(),equalTo("world"));
	 * }
	 * 
* @return */ public final HeadAndTail headAndTail(){ return StreamUtils.headAndTail(stream); } /** * extract head and tail together, where no head or tail may be present * *
	 * {@code 
	 * SequenceM helloWorld = SequenceM.of();
		Optional> headAndTail = helloWorld.headAndTailOptional();
		assertTrue(!headAndTail.isPresent());
	 * 
	 * }
	 * 
* @return */ public final Optional> headAndTailOptional(){ return StreamUtils.headAndTailOptional(stream); } /** * @return First matching element in sequential order * * (deterministic) * */ public final Optional findFirst() { return stream.findFirst(); } /** * @return first matching element, but order is not guaranteed * * (non-deterministic) */ public final Optional findAny() { return stream.findAny(); } /** * Attempt to map this Monad to the same type as the supplied Monoid (using mapToType on the monoid interface) * Then use Monoid to reduce values * * @param reducer Monoid to reduce values * @return Reduce result */ public final R mapReduce(Monoid reducer){ return reducer.mapReduce(stream); } /** * Attempt to map this Monad to the same type as the supplied Monoid, using supplied function * Then use Monoid to reduce values * * @param mapper Function to map Monad type * @param reducer Monoid to reduce values * @return Reduce result */ public final R mapReduce(Function mapper, Monoid reducer){ return reducer.reduce(stream.map(mapper)); } /** * Mutable reduction / collection over this Monad converted to a Stream * * @param collector Collection operation definition * @return Collected result */ public final R collect(Collector collector){ return stream.collect(collector); } /* (non-Javadoc) * @see java.util.stream.Stream#collect(java.util.function.Supplier, java.util.function.BiConsumer, java.util.function.BiConsumer) */ public final R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner){ return stream.collect(supplier, accumulator, combiner); } /** * Apply multiple collectors Simulataneously to this Monad * *
{@code
	  	List result =SequenceM.of(1,2,3).collect(Stream.of(Collectors.toList(),
	  															Collectors.summingInt(Integer::intValue),
	  															Collectors.averagingInt(Integer::intValue)));
		
		assertThat(result.get(0),equalTo(Arrays.asList(1,2,3)));
		assertThat(result.get(1),equalTo(6));
		assertThat(result.get(2),equalTo(2.0));
		}
* * @param collectors Stream of Collectors to apply * @return List of results */ public final List collect(Stream collectors){ return StreamUtils.collect(stream,collectors); } /** * Apply multiple Collectors, simultaneously to a Stream *
	 * {@code 
	 * List result = SequenceM.of(1,2,3).collect(
								Arrays.asList(Collectors.toList(),
								Collectors.summingInt(Integer::intValue),
								Collectors.averagingInt(Integer::intValue)));
		
		assertThat(result.get(0),equalTo(Arrays.asList(1,2,3)));
		assertThat(result.get(1),equalTo(6));
		assertThat(result.get(2),equalTo(2.0));
	 * }
	 * 
* @param stream Stream to collect * @param collectors Collectors to apply * @return Result as a list */ @SuppressWarnings({ "rawtypes", "unchecked" }) public List collectIterable(Iterable collectors){ return StreamUtils.collect(stream, collectors); } /** * * * @param reducer Use supplied Monoid to reduce values * @return reduced values */ public final T reduce(Monoid reducer){ return reducer.reduce(stream); } /* *
	 * {@code 
	 * assertThat(SequenceM.of(1,2,3,4,5).map(it -> it*100).reduce( (acc,next) -> acc+next).get(),equalTo(1500));
	 * }
	 * 
* */ public final Optional reduce(BinaryOperator accumulator){ return stream.reduce(accumulator); } /* (non-Javadoc) * @see java.util.stream.Stream#reduce(java.lang.Object, java.util.function.BinaryOperator) */ public final T reduce(T identity, BinaryOperator accumulator){ return stream.reduce(identity, accumulator); } /* (non-Javadoc) * @see java.util.stream.Stream#reduce(java.lang.Object, java.util.function.BiFunction, java.util.function.BinaryOperator) */ public final U reduce(U identity, BiFunction accumulator, BinaryOperator combiner){ return stream.reduce(identity, accumulator, combiner); } /** * Reduce with multiple reducers in parallel * NB if this Monad is an Optional [Arrays.asList(1,2,3)] reduce will operate on the Optional as if the list was one value * To reduce over the values on the list, called streamedStreamUtils.sequenceM() first. I.e. streamedStreamUtils.sequenceM().reduce(reducer) * * @param reducers * @return */ public final List reduce(Stream> reducers){ return StreamUtils.reduce(stream, reducers); } /** * Reduce with multiple reducers in parallel * NB if this Monad is an Optional [Arrays.asList(1,2,3)] reduce will operate on the Optional as if the list was one value * To reduce over the values on the list, called streamedStreamUtils.sequenceM() first. I.e. streamedStreamUtils.sequenceM().reduce(reducer) * * @param reducers * @return */ public final List reduce(Iterable> reducers){ return StreamUtils.reduce(stream, reducers); } /** * * * @param reducer Use supplied Monoid to reduce values starting via foldLeft * @return Reduced result */ public final T foldLeft(Monoid reducer){ return reduce(reducer); } /** * foldLeft : immutable reduction from left to right *
	 * {@code 
	 * 
	 * assertTrue(SequenceM.of("a", "b", "c").foldLeft("", String::concat).equals("abc"));
	 * }
	 * 
*/ public final T foldLeft(T identity, BinaryOperator accumulator){ return stream.reduce(identity, accumulator); } /** * Attempt to map this Monad to the same type as the supplied Monoid (using mapToType on the monoid interface) * Then use Monoid to reduce values * * @param reducer Monoid to reduce values * @return Reduce result */ public final T foldLeftMapToType(Monoid reducer){ return reducer.mapReduce(stream); } /** * * * @param reducer Use supplied Monoid to reduce values starting via foldRight * @return Reduced result */ public final T foldRight(Monoid reducer){ return reducer.reduce(reverse()); } /** * Immutable reduction from right to left *
	 * {@code 
	 *  assertTrue(SequenceM.of("a","b","c").foldRight("", String::concat).equals("cba"));
	 * }
	 * 
* * @param identity * @param accumulator * @return */ public final U foldRight(U seed, BiFunction function){ return stream.foldRight(seed, function); } /** * Attempt to map this Monad to the same type as the supplied Monoid (using mapToType on the monoid interface) * Then use Monoid to reduce values * * @param reducer Monoid to reduce values * @return Reduce result */ public final T foldRightMapToType(Monoid reducer){ return reducer.mapReduce(reverse()); } /** * @return Underlying Stream (lazily) converted to a Streamable instance */ public final Streamable toStreamable(){ return AsStreamable.fromStream(stream()); } /** * @return This monad converted to a set */ public final Set toSet(){ return (Set)stream.collect(Collectors.toSet()); } /** * @return this monad converted to a list */ public final List toList(){ return (List)stream.collect(Collectors.toList()); } public final > C toCollection(Supplier collectionFactory) { return stream.collect(Collectors.toCollection(collectionFactory)); } /** * @return calls to stream() but more flexible on type for inferencing purposes. */ public final Stream toStream(){ return (Stream) stream; } /** * Unwrap this Monad into a Stream. * If the underlying monad is a Stream it is returned * Otherwise we flatMap the underlying monad to a Stream type */ public final Stream stream(){ return stream; } /** * *
	 * {@code 
	 *  assertTrue(StreamUtils.sequenceM(Stream.of(1,2,3,4)).startsWith(Arrays.asList(1,2,3)));
	 * }
* * @param iterable * @return True if Monad starts with Iterable sequence of data */ public final boolean startsWith(Iterable iterable){ return StreamUtils.startsWith(stream,iterable); } /** *
{@code assertTrue(StreamUtils.sequenceM(Stream.of(1,2,3,4)).startsWith(Arrays.asList(1,2,3).iterator())) }
* @param iterator * @return True if Monad starts with Iterators sequence of data */ public final boolean startsWith(Iterator iterator){ return StreamUtils.startsWith(stream,iterator); } /** * @return this SequenceM converted to AnyM format */ public AnyM anyM(){ return AsGenericMonad.fromStream(stream).anyM(); } /* (non-Javadoc) * @see java.util.stream.Stream#map(java.util.function.Function) */ public final SequenceM map(Function fn){ return new SequenceMImpl(stream.map(fn)); } /* (non-Javadoc) * @see java.util.stream.Stream#peek(java.util.function.Consumer) */ public final SequenceM peek(Consumer c) { return new SequenceMImpl(stream.peek(c)); } /** * flatMap operation *
	 * {@code
	 * 	assertThat(this.of(1,2).flatMap(i -> asList(i, -i).stream()).toList(),equalTo(asList(1, -1, 2, -2)));		
 
	 * }
	 * 
* @param fn to be applied * @return new stage in Sequence with flatMap operation to be lazily applied */ public final SequenceM flatMap(Function> fn) { return StreamUtils.sequenceM(stream.flatMap(fn),reversable); } /** * Allows flatMap return type to be any Monad type *
	 * {@code 
	 * 	assertThat(anyM(Seq.of(1,2,3)).asSequence().flatMapAnyM(i-> anyM(CompletableFuture.completedFuture(i+2))).toList(),equalTo(Arrays.asList(3,4,5)));

	 * }
* * * @param fn to be applied * @return new stage in Sequence with flatMap operation to be lazily applied */ public final SequenceM flatMapAnyM(Function> fn) { return StreamUtils.sequenceM(StreamUtils.flatMapAnyM(stream,fn),reversable); } /** * Convenience method & performance optimisation * * flatMapping to a Stream will result in the Stream being converted to a List, if the host Monad * type is not a Stream. (i.e. *
	 *  {@code  
	 *   AnyM opt = anyM(Optional.of(20));
	 *   Optional> optionalList = opt.flatMap( i -> anyM(Stream.of(1,2,i))).unwrap();  
	 *   
	 *   //Optional [1,2,20]
	 *  }
* * In such cases using Arrays.asList would be more performant *
	 *  {@code  
	 *   AnyM opt = anyM(Optional.of(20));
	 *   Optional> optionalList = opt.flatMapCollection( i -> asList(1,2,i))).unwrap();  
	 *   
	 *   //Optional [1,2,20]
	 *  }
* @param fn * @return */ public final SequenceM flatMapCollection(Function> fn) { return StreamUtils.sequenceM(StreamUtils.flatMapCollection(stream,fn),Optional.empty()); } /** * flatMap operation * *
	 * {@code 
	 * 	assertThat(anyM(Stream.of(1,2,3)).asSequence().flatMapStream(i->Stream.of(i)).toList(),equalTo(Arrays.asList(1,2,3)));

	 * }
	 * 
* * @param fn to be applied * @return new stage in Sequence with flatMap operation to be lazily applied */ public final SequenceM flatMapStream(Function> fn) { return StreamUtils.sequenceM(StreamUtils.flatMapStream(stream,fn),reversable); } /** * flatMap to optional - will result in null values being removed *
	 * {@code 
	 * 	assertThat(SequenceM.of(1,2,3,null).flatMapOptional(Optional::ofNullable)
			      										.collect(Collectors.toList()),
			      										equalTo(Arrays.asList(1,2,3)));
	 * }
	 * 
* @param fn * @return */ public final SequenceM flatMapOptional(Function> fn) { return StreamUtils.sequenceM(StreamUtils.flatMapOptional(stream,fn),reversable); } /** * flatMap to CompletableFuture - will block until Future complete, although (for non-blocking behaviour use AnyM * wrapping CompletableFuture and flatMap to Stream there) * *
	 *  {@code
	 *  	assertThat(SequenceM.of(1,2,3).flatMapCompletableFuture(i->CompletableFuture.completedFuture(i+2))
				  								.collect(Collectors.toList()),
				  								equalTo(Arrays.asList(3,4,5)));
	 *  }
	 *  
* * @param fn * @return */ public final SequenceM flatMapCompletableFuture(Function> fn) { return StreamUtils.sequenceM(StreamUtils.flatMapCompletableFuture(stream,fn),reversable); } /** * Perform a flatMap operation where the result will be a flattened stream of Characters * from the CharSequence returned by the supplied function. * *
	 * {@code 
	 *   List result = anyM("input.file")
									.asSequence()
									.flatMapCharSequence(i->"hello world")
									.toList();
		
		assertThat(result,equalTo(Arrays.asList('h','e','l','l','o',' ','w','o','r','l','d')));
	 * }
	 * 
* * @param fn * @return */ public final SequenceM flatMapCharSequence(Function fn) { return StreamUtils.sequenceM(StreamUtils.flatMapCharSequence(stream, fn),reversable); } /** * Perform a flatMap operation where the result will be a flattened stream of Strings * from the text loaded from the supplied files. * *
	 * {@code
	 * 
		List result = anyM("input.file")
								.asSequence()
								.map(getClass().getClassLoader()::getResource)
								.peek(System.out::println)
								.map(URL::getFile)
								.liftAndBindFile(File::new)
								.toList();
		
		assertThat(result,equalTo(Arrays.asList("hello","world")));
	 * 
	 * }
	 * 
	 * 
* * @param fn * @return */ public final SequenceM flatMapFile(Function fn) { return StreamUtils.sequenceM(StreamUtils.flatMapFile(stream, fn),reversable); } /** * Perform a flatMap operation where the result will be a flattened stream of Strings * from the text loaded from the supplied URLs * *
	 * {@code 
	 * List result = anyM("input.file")
								.asSequence()
								.liftAndBindURL(getClass().getClassLoader()::getResource)
								.toList();
		
		assertThat(result,equalTo(Arrays.asList("hello","world")));
	 * 
	 * }
	 * 
* * @param fn * @return */ public final SequenceM flatMapURL(Function fn) { return StreamUtils.sequenceM(StreamUtils.flatMapURL(stream, fn),reversable); } /** * Perform a flatMap operation where the result will be a flattened stream of Strings * from the text loaded from the supplied BufferedReaders * *
	 * List result = anyM("input.file")
								.asSequence()
								.map(getClass().getClassLoader()::getResourceAsStream)
								.map(InputStreamReader::new)
								.liftAndBindBufferedReader(BufferedReader::new)
								.toList();
		
		assertThat(result,equalTo(Arrays.asList("hello","world")));
	 * 
	 * 
* * * @param fn * @return */ public final SequenceM flatMapBufferedReader(Function fn) { return StreamUtils.sequenceM(StreamUtils.flatMapBufferedReader(stream, fn),reversable); } public final SequenceM filter(Predicate fn){ return StreamUtils.sequenceM(stream.filter(fn),reversable); } public void forEach(Consumer action) { stream.forEach(action); } public Iterator iterator() { return stream.iterator(); } public Spliterator spliterator() { return stream.spliterator(); } public boolean isParallel() { return stream.isParallel(); } public SequenceM sequential() { return StreamUtils.sequenceM(stream.sequential(),reversable); } public SequenceM unordered() { return StreamUtils.sequenceM(stream.unordered(),reversable); } public IntStream mapToInt(ToIntFunction mapper) { return stream.mapToInt(mapper); } public LongStream mapToLong(ToLongFunction mapper) { return stream.mapToLong(mapper); } public DoubleStream mapToDouble(ToDoubleFunction mapper) { return stream.mapToDouble(mapper); } public IntStream flatMapToInt( Function mapper) { return stream.flatMapToInt(mapper); } public LongStream flatMapToLong( Function mapper) { return stream.flatMapToLong(mapper); } public DoubleStream flatMapToDouble( Function mapper) { return stream.flatMapToDouble(mapper); } public void forEachOrdered(Consumer action) { stream.forEachOrdered(action); } public Object[] toArray() { return stream.toArray(); } public A[] toArray(IntFunction generator) { return stream.toArray(generator); } public long count() { return stream.count(); } /** * Returns a stream with a given value interspersed between any two values * of this stream. * * * // (1, 0, 2, 0, 3, 0, 4) SequenceM.of(1, 2, 3, 4).intersperse(0) * */ public SequenceM intersperse(T value) { return StreamUtils.sequenceM(stream.flatMap(t -> Stream.of(value,t)).skip(1l),reversable); } /** * Keep only those elements in a stream that are of a given type. * * * // (1, 2, 3) SequenceM.of(1, "a", 2, "b",3).ofType(Integer.class) * */ @SuppressWarnings("unchecked") public SequenceM ofType(Class type) { return StreamUtils.sequenceM(StreamUtils.ofType(stream, type),reversable); } /** * Cast all elements in a stream to a given type, possibly throwing a * {@link ClassCastException}. * * * // ClassCastException SequenceM.of(1, "a", 2, "b", 3).cast(Integer.class) * */ public SequenceM cast(Class type) { return StreamUtils.sequenceM(StreamUtils.cast(stream, type),reversable); } /** * Lazily converts this SequenceM into a Collection. This does not trigger the Stream. E.g. * Collection is not thread safe on the first iteration. *
	 * {@code 
	 * Collection col = SequenceM.of(1,2,3,4,5)
											.peek(System.out::println)
											.toLazyCollection();
		System.out.println("first!");
		col.forEach(System.out::println);
	 * }
	 * 
	 * //Will print out "first!" before anything else
	 * 
* @return */ public Collection toLazyCollection(){ return StreamUtils.toLazyCollection(stream); } /** * Lazily converts this SequenceM into a Collection. This does not trigger the Stream. E.g. * *
	 * {@code 
	 * Collection col = SequenceM.of(1,2,3,4,5)
											.peek(System.out::println)
											.toConcurrentLazyCollection();
		System.out.println("first!");
		col.forEach(System.out::println);
	 * }
	 * 
	 * //Will print out "first!" before anything else
	 * 
* @return */ public Collection toConcurrentLazyCollection(){ return StreamUtils.toConcurrentLazyCollection(stream); } /** * @return Streamable that can replay this SequenceM */ public Streamable toLazyStreamable(){ return StreamUtils.toLazyStreamable(stream); } /** * @return Streamable that replay this SequenceM */ public Streamable toConcurrentLazyStreamable(){ return StreamUtils.toConcurrentLazyStreamable(stream); } public SequenceM reverse(){ if(reversable.isPresent()){ reversable.ifPresent(r->r.invert()); return this; } return StreamUtils.sequenceM(StreamUtils.reverse(stream),reversable); } @Override public SequenceM onClose(Runnable closeHandler) { return this; } @Override public void close() { } public SequenceM shuffle() { return StreamUtils.sequenceM(StreamUtils.shuffle(stream).stream(),reversable); } /** * Append Stream to this SequenceM * *
	 * {@code 
	 * List result = 	of(1,2,3).appendStream(of(100,200,300))
										.map(it ->it+"!!")
										.collect(Collectors.toList());

			assertThat(result,equalTo(Arrays.asList("1!!","2!!","3!!","100!!","200!!","300!!")));
	 * }
	 * 
* * @param stream to append * @return SequenceM with Stream appended */ public SequenceM appendStream(Stream stream) { return StreamUtils.sequenceM(StreamUtils.appendStream(this.stream,stream),Optional.empty()); } /** * Prepend Stream to this SequenceM * *
	 * {@code 
	 * List result = of(1,2,3).prependStream(of(100,200,300))
				.map(it ->it+"!!").collect(Collectors.toList());

			assertThat(result,equalTo(Arrays.asList("100!!","200!!","300!!","1!!","2!!","3!!")));
	 * 
	 * }
	 * 
* * @param stream to Prepend * @return SequenceM with Stream prepended */ public SequenceM prependStream(Stream stream) { return StreamUtils.sequenceM(StreamUtils.prependStream(this.stream,stream),Optional.empty()); } /** * Append values to the end of this SequenceM *
	 * {@code 
	 * List result = 	of(1,2,3).append(100,200,300)
										.map(it ->it+"!!")
										.collect(Collectors.toList());

			assertThat(result,equalTo(Arrays.asList("1!!","2!!","3!!","100!!","200!!","300!!")));
	 * }
	 * 
* @param values to append * @return SequenceM with appended values */ public SequenceM append(T... values) { return StreamUtils.sequenceM(StreamUtils.append(stream, values),Optional.empty()); } /** * Prepend given values to the start of the Stream *


	 * {@code 
	 * List result = 	of(1,2,3).prepend(100,200,300)
				.map(it ->it+"!!").collect(Collectors.toList());

			assertThat(result,equalTo(Arrays.asList("100!!","200!!","300!!","1!!","2!!","3!!")));
	 * }
	 * @param values to prepend
	 * @return SequenceM with values prepended
	 */
	public SequenceM prepend(T... values) {
		return StreamUtils.sequenceM(StreamUtils.prepend(stream, values),Optional.empty());
	}
	/**
	 * Insert data into a stream at given position
	 * 
	 * {@code 
	 * List result = 	of(1,2,3).insertAt(1,100,200,300)
				.map(it ->it+"!!").collect(Collectors.toList());

			assertThat(result,equalTo(Arrays.asList("1!!","100!!","200!!","300!!","2!!","3!!")));
	 * 
	 * }
	 * 
* @param pos to insert data at * @param values to insert * @return Stream with new data inserted */ public SequenceM insertAt(int pos, T... values) { return StreamUtils.sequenceM(StreamUtils.insertAt(stream, pos, values),Optional.empty()); } /** * Delete elements between given indexes in a Stream *
	 * {@code 
	 * List result = 	of(1,2,3,4,5,6).deleteBetween(2,4)
				.map(it ->it+"!!").collect(Collectors.toList());

			assertThat(result,equalTo(Arrays.asList("1!!","2!!","5!!","6!!")));
	 * }
	 * 
* @param start index * @param end index * @return Stream with elements removed */ public SequenceM deleteBetween(int start,int end) { return StreamUtils.sequenceM(StreamUtils.deleteBetween(stream, start, end),Optional.empty()); } /** * Insert a Stream into the middle of this stream at the specified position *
	 * {@code 
	 * List result = 	of(1,2,3).insertStreamAt(1,of(100,200,300))
				.map(it ->it+"!!").collect(Collectors.toList());

			assertThat(result,equalTo(Arrays.asList("1!!","100!!","200!!","300!!","2!!","3!!")));
	 * }
	 * 
* @param pos to insert Stream at * @param stream to insert * @return newly conjoined SequenceM */ public SequenceM insertStreamAt(int pos, Stream stream) { return StreamUtils.sequenceM(StreamUtils.insertStreamAt(this.stream, pos,stream),Optional.empty()); } @Override public FutureOperations futureOperations(Executor exec) { return StreamUtils.futureOperations(stream,exec); } @Override public boolean endsWith(Iterable iterable) { return StreamUtils.endsWith(stream, iterable); } @Override public HotStream hotStream(Executor e) { return StreamUtils.hotStream(stream, e); } @Override public T firstValue() { return StreamUtils.firstValue(stream); } @Override public void subscribe(Subscriber s) { ReactiveStreamsLoader.publisher.get().subscribe(stream,s); } @Override public SequenceM> zip(Seq other) { return StreamUtils.sequenceM(stream.zip(other),reversable); } @Override public SequenceM zipAnyM(AnyM second, BiFunction zipper) { return StreamUtils.sequenceM(StreamUtils.zipAnyM(stream,second,zipper),reversable); } @Override public SequenceM> crossJoin(Stream other) { return StreamUtils.sequenceM(stream.crossJoin(other),reversable); } @Override public SequenceM> innerJoin(Stream other, BiPredicate predicate) { return StreamUtils.sequenceM(stream.innerJoin(other, predicate),reversable); } @Override public SequenceM> leftOuterJoin(Stream other, BiPredicate predicate) { return StreamUtils.sequenceM(stream.leftOuterJoin(other, predicate),reversable); } @Override public SequenceM> rightOuterJoin(Stream other, BiPredicate predicate) { return StreamUtils.sequenceM(stream.rightOuterJoin(other, predicate),reversable); } @Override public SequenceM onEmpty(T value) { return StreamUtils.sequenceM(stream.onEmpty(value),Optional.empty()); } @Override public SequenceM onEmptyGet(Supplier supplier) { return StreamUtils.sequenceM(stream.onEmptyGet(supplier),Optional.empty()); } @Override public SequenceM onEmptyThrow(Supplier supplier) { return StreamUtils.sequenceM(stream.onEmptyThrow(supplier),Optional.empty()); } @Override public SequenceM concat(Stream other) { return StreamUtils.sequenceM(stream.concat(other),Optional.empty()); } @Override public SequenceM concat(T other) { return StreamUtils.sequenceM(stream.concat(other),Optional.empty()); } @Override public SequenceM concat(T... other) { return StreamUtils.sequenceM(stream.concat(other),Optional.empty()); } @Override public SequenceM distinct( Function keyExtractor) { return StreamUtils.sequenceM(stream.distinct(keyExtractor),reversable); } @Override public SequenceM zip(Seq other, BiFunction zipper) { return StreamUtils.sequenceM(stream.zip(other, zipper),Optional.empty()); } @Override public SequenceM shuffle(Random random) { return StreamUtils.sequenceM(stream.shuffle(random),reversable); } @Override public SequenceM slice(long from, long to) { return StreamUtils.sequenceM(stream.slice(from,to),reversable); } @Override public > SequenceM sorted( Function function) { return StreamUtils.sequenceM(stream.sorted(function),reversable); } @Override public SequenceM> zipStream(Stream other) { return StreamUtils.sequenceM(StreamUtils.zipStream(stream, other,Tuple::tuple),Optional.empty()); } @Override public SequenceM xPer(int x, long time, TimeUnit t) { return StreamUtils.sequenceM(StreamUtils.xPer(stream, x,time,t),reversable); } @Override public SequenceM onePer(long time, TimeUnit t) { return StreamUtils.sequenceM(StreamUtils.onePer(stream,time,t),reversable); } @Override public SequenceM debounce(long time, TimeUnit t) { return StreamUtils.sequenceM(StreamUtils.debounce(stream, time,t),reversable); } @Override public SequenceM> batchBySizeAndTime(int size, long time, TimeUnit t) { return StreamUtils.sequenceM(StreamUtils.batchBySizeAndTime(stream, size, time,t),reversable); } @Override public SequenceM> batchByTime(long time, TimeUnit t) { return StreamUtils.sequenceM(StreamUtils.batchByTime(stream, time,t),reversable); } @Override public T foldRight(T identity, BinaryOperator accumulator) { return reverse().foldLeft(identity, accumulator); } @Override public boolean endsWith(Stream iterable) { return StreamUtils.endsWith(stream,()->iterable.iterator()); } @Override public SequenceM skip(long time, TimeUnit unit) { return StreamUtils.sequenceM(StreamUtils.skip(stream,time,unit), this.reversable); } @Override public SequenceM limit(long time, TimeUnit unit) { return StreamUtils.sequenceM(StreamUtils.limit(stream,time,unit), this.reversable); } @Override public SequenceM> batchBySize(int size) { return StreamUtils.sequenceM(StreamUtils.batchBySize(stream, size),this.reversable); } @Override public SequenceM fixedDelay(long l, TimeUnit unit) { return StreamUtils.sequenceM(StreamUtils.fixedDelay(stream,l,unit), this.reversable); } @Override public SequenceM jitter(long l) { return StreamUtils.sequenceM(StreamUtils.jitter(stream,l), this.reversable); } @Override public SequenceM> windowBySizeAndTime(int size, long time, TimeUnit t) { return StreamUtils.sequenceM(StreamUtils.windowBySizeAndTime(stream,size,time,t), this.reversable); } @Override public SequenceM> windowWhile(Predicate predicate) { return StreamUtils.sequenceM(StreamUtils.windowWhile(stream,predicate), this.reversable); } @Override public SequenceM> windowUntil(Predicate predicate) { return StreamUtils.sequenceM(StreamUtils.windowWhile(stream,predicate.negate()), this.reversable); } @Override public SequenceM> windowStatefullyWhile( BiPredicate, T> predicate) { return StreamUtils.sequenceM(StreamUtils.windowStatefullyWhile(stream, predicate), this.reversable); } @Override public SequenceM> windowByTime(long time, TimeUnit t) { return StreamUtils.sequenceM(StreamUtils.windowByTime(stream, time,t), this.reversable); } @Override public SequenceM> batchUntil(Predicate predicate) { return StreamUtils.sequenceM(StreamUtils.batchUntil(stream,predicate), this.reversable); } @Override public SequenceM> batchWhile(Predicate predicate) { return StreamUtils.sequenceM(StreamUtils.batchWhile(stream,predicate), this.reversable); } @Override public List collectStream(Stream collectors) { return StreamUtils.collect(stream,collectors); } @Override public> SequenceM batchWhile(Predicate predicate, Supplier factory) { return StreamUtils.sequenceM(StreamUtils.batchWhile(stream,predicate,factory), this.reversable); } @Override public> SequenceM batchUntil(Predicate predicate, Supplier factory) { return StreamUtils.sequenceM(StreamUtils.batchWhile(stream,predicate.negate(),factory), this.reversable); } @Override public > SequenceM batchBySizeAndTime(int size, long time, TimeUnit unit, Supplier factory) { return StreamUtils.sequenceM(StreamUtils.batchBySizeAndTime(stream, size,time, unit, factory),this.reversable); } @Override public > SequenceM batchByTime(long time, TimeUnit unit, Supplier factory) { return StreamUtils.sequenceM(StreamUtils.batchByTime(stream, time, unit, factory),this.reversable); } @Override public > SequenceM batchBySize(int size, Supplier factory) { return StreamUtils.sequenceM(StreamUtils.batchBySize(stream, size,factory),this.reversable); } @Override public SequenceM skipLast(int num) { return StreamUtils.sequenceM(StreamUtils.skipLast(stream,num),this.reversable); } @Override public SequenceM limitLast(int num) { return StreamUtils.sequenceM(StreamUtils.limitLast(stream,num),this.reversable); } @Override public SequenceM recover(Function fn) { return StreamUtils.sequenceM(StreamUtils.recover(stream,fn),this.reversable); } @Override public SequenceM recover(Class exceptionClass, Function fn) { return StreamUtils.sequenceM(StreamUtils.recover(stream,exceptionClass,fn),this.reversable); } }