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

functionalj.stream.StreamPlusHelper Maven / Gradle / Ivy

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

import java.util.Iterator;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import lombok.val;


public class StreamPlusHelper {
    
    static final Object dummy = new Object();
    
    public static  boolean hasAt(Stream stream, long index) {
        return hasAt(stream, index, null);
    }
    
    public static  boolean hasAt(Stream stream, long index, AtomicReference StreamPlusValue) {
        // Note: It is done this way to avoid interpreting 'null' as no-value
        
        val ref = new AtomicReference(dummy);
        stream
            .skip(index)
            .peek(value -> ref.set(value))
            .findFirst()
            .orElse(null);
        
        @SuppressWarnings("unchecked")
        val value = (T)ref.get();
        val found = (dummy != value);
        
        if (StreamPlusValue != null) {
            StreamPlusValue.set(found ? value : null);
        }
        
        return found;
    }
    
    static  IteratorPlus rawIterator(Stream stream) {
        return IteratorPlus.from(stream);
    }
    
    static  StreamPlus derive(
            AsStreamPlus                asStreamPlus,
            Function, Stream> action) {
        val streamPlus = asStreamPlus.streamPlus();
        val orgStream  = streamPlus.stream();
        val newStream  = action.apply(orgStream);
        return StreamPlus.from(newStream);
    }
    
    //-- Terminal --
    
    static  TARGET terminate(
            AsStreamPlus             asStreamPlus,
            Function, TARGET> action) {
        val streamPlus = asStreamPlus.streamPlus();
        try {
            val stream = streamPlus.stream();
            val result = action.apply(stream);
            return result;
        } finally {
            streamPlus.close();
        }
    }
    
    static  void terminate(
            AsStreamPlus     asStreamPlus,
            Consumer> action) {
        val streamPlus = asStreamPlus.streamPlus();
        try {
            val stream = streamPlus.stream();
            action.accept(stream);
        } finally {
            streamPlus.close();
        }
    }
    
    /** Run the given action sequentially, make sure to set the parallelity of the result back. */
    static  StreamPlus sequential(
            AsStreamPlus                        asStreamPlus,
            Function, StreamPlus> action) {
        val streamPlus = asStreamPlus.streamPlus();
        val isParallel = streamPlus.isParallel();
        
        val orgIntStreamPlus = streamPlus.sequential();
        val newIntStreamPlus = action.apply(orgIntStreamPlus);
        if (newIntStreamPlus.isParallel() == isParallel)
            return newIntStreamPlus;
        
        if (isParallel)
            return newIntStreamPlus.parallel();
        
        return newIntStreamPlus.sequential();
    }
    
    /** Run the given action sequentially, make sure to set the parallelity of the result back. */
    static  StreamPlus sequentialToObj(
            AsStreamPlus                        asStreamPlus,
            Function, StreamPlus> action) {
        return sequential(asStreamPlus, action);
    }
    
    static  StreamPlus doZipWith(
            ZipWithOption          option, 
            BiFunction merger,
            IteratorPlus     iteratorA, 
            IteratorPlus        iteratorB) {
        
        val iterator = new Iterator() {
            private boolean hasNextA;
            private boolean hasNextB;
            
            public boolean hasNext() {
                hasNextA = iteratorA.hasNext();
                hasNextB = iteratorB.hasNext();
                return (option == ZipWithOption.RequireBoth)
                        ? (hasNextA && hasNextB)
                        : (hasNextA || hasNextB);
            }
            public C next() {
                val nextA = hasNextA ? iteratorA.next() : null;
                val nextB = hasNextB ? iteratorB.next() : null;
                return merger.apply(nextA, nextB);
            }
        };
        val iterable = new Iterable() {
            @Override
            public Iterator iterator() {
                return iterator;
            }
          
        };
        return StreamPlus.from(StreamSupport.stream(iterable.spliterator(), false));
    }
    
    static  StreamPlus doMerge(
            Iterator iteratorA, 
            Iterator iteratorB) {
        val iterable = new Iterable() {
            private final Iterator iterator = new Iterator() {
                private boolean isA = true;
                
                public boolean hasNext() {
                    if (isA) {
                        if (iteratorA.hasNext()) return true;
                        isA = false;
                        if (iteratorB.hasNext()) return true;
                        return false;
                    }
                    
                    if (iteratorB.hasNext()) return true;
                    isA = true;
                    if (iteratorA.hasNext()) return true;
                    return false;
                }
                public DATA next() {
                    val next = isA ? iteratorA.next() : iteratorB.next();
                    isA = !isA;
                    return next;
                }
            };
            @Override
            public Iterator iterator() {
                return iterator;
            }
        };
        val spliterator = iterable.spliterator();
        val stream      = StreamSupport.stream(spliterator, false);
        return StreamPlus.from(stream);
    }
    
}