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

functionalj.stream.StreamPlusWithCombine Maven / Gradle / Ivy

There is a newer version: 1.0.17
Show newest version
package functionalj.stream;

import static functionalj.function.FuncUnit0.funcUnit0;
import static functionalj.stream.ZipWithOption.AllowUnpaired;

import java.util.stream.Stream;

import functionalj.function.Func1;
import functionalj.function.Func2;
import functionalj.tuple.Tuple2;
import lombok.val;

public interface StreamPlusWithCombine {
    
    public Stream      stream();
    public  StreamPlus useIterator(Func1, StreamPlus> action);
    
    
    @SuppressWarnings("unchecked")
    public default StreamPlus concatWith(
            Stream tail) {
        return StreamPlus.concat(
                StreamPlus.of(this), 
                StreamPlus.of(tail)
               )
               .flatMap(s -> (StreamPlus)s);
    }
    
    public default StreamPlus merge(Stream anotherStream) {
        val thisStream = stream();
        val iteratorA  = StreamPlusHelper.rawIterator(thisStream);
        val iteratorB  = StreamPlusHelper.rawIterator(anotherStream);
        
        val resultStream 
                = StreamPlusHelper
                .doMerge(iteratorA, iteratorB);
        
        resultStream
                .onClose(()->{
                    funcUnit0(()->thisStream   .close()).runCarelessly();
                    funcUnit0(()->anotherStream.close()).runCarelessly();
                });
        return resultStream;
    }
    
    //-- Zip --
    
    public default  StreamPlus combineWith(Stream anotherStream, Func2 combinator) {
        return zipWith(anotherStream, ZipWithOption.RequireBoth)
                .map(combinator::applyTo);
    }
    public default  StreamPlus combineWith(Stream anotherStream, ZipWithOption option, Func2 combinator) {
        return zipWith(anotherStream, option)
                .map(combinator::applyTo);
    }
    
    public default  StreamPlus> zipWith(Stream anotherStream) {
        return zipWith(anotherStream, ZipWithOption.RequireBoth, Tuple2::of);
    }
    public default  StreamPlus> zipWith(Stream anotherStream, ZipWithOption option) {
        return zipWith(anotherStream, option, Tuple2::of);
    }
    
    public default  StreamPlus zipWith(Stream anotherStream, Func2 merger) {
        return zipWith(anotherStream, ZipWithOption.RequireBoth, merger);
    }
    // https://stackoverflow.com/questions/24059837/iterate-two-java-8-streams-together?noredirect=1&lq=1
    public default  StreamPlus zipWith(Stream anotherStream, ZipWithOption option, Func2 merger) {
        return useIterator(iteratorA -> {
            return StreamPlus
                    .from(anotherStream)
                    .useIterator(iteratorB -> {
                        return StreamPlusHelper.doZipWith(option, merger, iteratorA, iteratorB);
                    });
        });
    }
    
    public default StreamPlus choose(Stream anotherStream, Func2 selectThisNotAnother) {
        return zipWith(anotherStream, AllowUnpaired)
                .map(t -> {
                    val _1 = t._1();
                    val _2 = t._2();
                    if ((_1 != null) && _2 == null)
                        return _1;
                    if ((_1 == null) && _2 != null)
                        return _2;
                    if ((_1 == null) && _2 == null)
                        return null;
                    val which = selectThisNotAnother.applyTo(t);
                    return which ? _1 : _2;
                })
                .filterNonNull();
    }
    
}