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 static functionalj.functions.ObjFuncs.notEqual;
import static functionalj.stream.ZipWithOption.AllowUnpaired;
import static java.lang.Boolean.TRUE;

import java.util.Iterator;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import functionalj.function.Func2;
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  boolean equals(Stream stream1, Stream stream2) {
        return !StreamPlus
                .from       (stream1)
                .combineWith(StreamPlus.from(stream2), AllowUnpaired, notEqual())
                .filter     (TRUE::equals)
                .findAny    ()
                .isPresent  ();
    }
    
    public static  int hashCode(Stream stream) {
        return stream
                .mapToInt(e -> (e == null) ? 0 : e.hashCode())
                .reduce(1, (h, eh) -> 31*h + eh);
    }
    
    public static  String toString(Stream stream) {
        return "[" + StreamPlus.from(stream).joinToString(", ") + "]";
    }
    
    static  StreamPlus doZipWith(
            ZipWithOption      option, 
            Func2  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);
    }
    
    static  IteratorPlus rawIterator(Stream stream) {
        return IteratorPlus.from(stream);
    }
    
}