Przeglądaj źródła

new: CQuery# mapIf, unfoldIf, flatIf, splitIf
new: IteratorUtils# singleton

Mariusz Czarnowski 4 lat temu
rodzic
commit
ff1a099793

+ 91 - 5
assira.core/src/main/java/net/ranides/assira/collection/iterators/IteratorUtils.java

@@ -7,10 +7,7 @@
 package net.ranides.assira.collection.iterators;
 
 import java.util.*;
-import java.util.function.BiPredicate;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
+import java.util.function.*;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
@@ -232,6 +229,14 @@ public final class IteratorUtils {
         };
     }
 
+    public static <T> Iterator<T> singletonIterator(T value) {
+	    return new SingleIterator<>(value);
+    }
+
+    public static <T> Spliterator<T> singletonSpliterator(T value) {
+        return new SingleSpliterator<>(value);
+    }
+
     private static final class Adapter<S, T> implements Iterator<T> {
     
         protected final Iterator<S> delegate;
@@ -707,5 +712,86 @@ public final class IteratorUtils {
         }
 
     }
-    
+
+    private static class SingleIterator<T> implements Iterator<T> {
+
+        private final T value;
+
+        private boolean hasNext = true;
+
+        public SingleIterator(T value) {
+            this.value = value;
+        }
+
+        public boolean hasNext() {
+            return hasNext && value != null;
+        }
+
+        @Override
+        public T next() {
+            if (hasNext()) {
+                hasNext = false;
+                return value;
+            }
+            throw new NoSuchElementException();
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void forEachRemaining(Consumer<? super T> action) {
+            Objects.requireNonNull(action);
+            if (hasNext()) {
+                action.accept(value);
+                hasNext = false;
+            }
+        }
+    }
+
+    private static class SingleSpliterator<T> implements Spliterator<T> {
+
+	    private final T value;
+
+        long est = 1;
+
+        public SingleSpliterator(T value) {
+            this.value = value;
+        }
+
+        @Override
+        public Spliterator<T> trySplit() {
+            return null;
+        }
+
+        @Override
+        public boolean tryAdvance(Consumer<? super T> consumer) {
+            Objects.requireNonNull(consumer);
+            if (est > 0) {
+                est--;
+                consumer.accept(value);
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public void forEachRemaining(Consumer<? super T> consumer) {
+            tryAdvance(consumer);
+        }
+
+        @Override
+        public long estimateSize() {
+            return est;
+        }
+
+        @Override
+        public int characteristics() {
+            int out = (value != null) ? Spliterator.NONNULL : 0;
+
+            return out | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE |
+                    Spliterator.DISTINCT | Spliterator.ORDERED;
+        }
+    };
 }

+ 11 - 0
assira.core/src/main/java/net/ranides/assira/collection/query/CQuery.java

@@ -17,6 +17,7 @@ import java.util.stream.StreamSupport;
 import net.ranides.assira.collection.HashFunction;
 import net.ranides.assira.functional.Consumers.EachConsumer;
 import net.ranides.assira.functional.Functions.EachFunction;
+import net.ranides.assira.functional.Predicates.EachPredicate;
 import net.ranides.assira.functional.checked.CheckedFunction;
 import net.ranides.assira.functional.checked.CheckedSupplier;
 import net.ranides.assira.reflection.*;
@@ -99,6 +100,16 @@ public interface CQuery<T> extends Iterable<T> {
     <R> CQuery<R> flat(Function<? super T, Iterable<R>> f);
 
     <R> CQuery<R> split(Function<? super T, R[]> f);
+
+    CQuery<T> mapIf(Predicate<? super T> p, Function<? super T,? extends T> f);
+
+    CQuery<T> mapIf(EachPredicate<? super T> p, EachFunction<? super T,? extends T> f);
+
+    CQuery<T> unfoldIf(Predicate<? super T> p, Function<? super T, CQuery<T>> f);
+
+    CQuery<T> flatIf(Predicate<? super T> p, Function<? super T, Iterable<T>> f);
+
+    CQuery<T> splitIf(Predicate<? super T> p, Function<? super T, T[]> f);
     
     T fold(T identity, BinaryOperator<T> accumulator);
     

+ 82 - 3
assira.core/src/main/java/net/ranides/assira/collection/query/CQueryAbstract.java

@@ -26,8 +26,7 @@ import net.ranides.assira.collection.sets.HashSet;
 import net.ranides.assira.collection.sets.RBTreeSet;
 import net.ranides.assira.functional.Consumers.EachConsumer;
 import net.ranides.assira.functional.Functions.EachFunction;
-import net.ranides.assira.functional.checked.CheckedFunction;
-import net.ranides.assira.functional.checked.CheckedSupplier;
+import net.ranides.assira.functional.Predicates.EachPredicate;
 import net.ranides.assira.functional.special.Fold;
 import net.ranides.assira.generic.CompareUtils;
 import net.ranides.assira.generic.SerializationUtils;
@@ -147,21 +146,46 @@ public abstract class CQueryAbstract<T> implements CQuery<T> {
         return new CQIterable<>(() -> IteratorUtils.map(iterator(), f));
     }
 
+    @Override
+    public CQuery<T> mapIf(Predicate<? super T> p, Function<? super T, ? extends T> f) {
+        return map(v -> p.test(v) ? v : f.apply(v));
+    }
+
+    @Override
+    public CQuery<T> mapIf(EachPredicate<? super T> p, EachFunction<? super T, ? extends T> f) {
+        return map((i,v) -> p.test(i, v) ? v : f.apply(i,v));
+    }
+
     @Override
     public final <R> CQuery<R> unfold(Function<? super T, CQuery<R>> f) {
         return new CQIterable<>(() -> IteratorUtils.flat(IteratorUtils.map(iterator(), (v) -> f.apply(v).iterator())));
     }
 
+    @Override
+    public CQuery<T> unfoldIf(Predicate<? super T> p, Function<? super T, CQuery<T>> f) {
+        return flat(v -> p.test(v) ? Collections.singleton(v) : f.apply(v));
+    }
+
     @Override
     public final <R> CQuery<R> flat(Function<? super T, Iterable<R>> f) {
         return new CQIterable<>(() -> IteratorUtils.flat(IteratorUtils.map(iterator(), (v) -> f.apply(v).iterator())));
     }
 
+    @Override
+    public CQuery<T> flatIf(Predicate<? super T> p, Function<? super T, Iterable<T>> f) {
+        return flat(v -> p.test(v) ? Collections.singleton(v) : f.apply(v));
+    }
+
     @Override
     public <R> CQuery<R> split(Function<? super T, R[]> f) {
         return unfold(v -> CQuery.from().array(f.apply(v)) );
     }
 
+    @Override
+    public CQuery<T> splitIf(Predicate<? super T> p, Function<? super T, T[]> f) {
+        return flat(v -> p.test(v) ? Collections.singleton(v) : Arrays.asList(f.apply(v)));
+    }
+
     @Override
     public final T fold(T identity, BinaryOperator<T> accumulator) {
         Iterator<T> i = iterator();
@@ -412,7 +436,7 @@ public abstract class CQueryAbstract<T> implements CQuery<T> {
         }
 
     }
-        
+
     protected static class CQIterable<T> extends CQueryAbstract<T> {
         
         private final Supplier<Iterable<T>> source;
@@ -557,6 +581,61 @@ public abstract class CQueryAbstract<T> implements CQuery<T> {
         }
     }
 
+    protected static class CQSingle<T> extends CQueryAbstract<T> {
+
+        private final T value;
+
+        public CQSingle(T value) {
+            this.value = value;
+        }
+
+        @Override
+        public Iterator<T> iterator() {
+            return IteratorUtils.singletonIterator(value);
+        }
+
+        @Override
+        public Spliterator<T> spliterator() {
+            return IteratorUtils.singletonSpliterator(value);
+        }
+
+        @Override
+        public Stream<T> stream() {
+            return Stream.of(value);
+        }
+
+        @Override
+        public int size() {
+            return 1;
+        }
+
+        @Override
+        public CQuery<T> limit(int n) {
+            return n == 0 ? CQuery.empty() : this;
+        }
+
+        @Override
+        public CQuery<T> skip(int n) {
+            return n > 0 ? CQuery.empty() : this;
+        }
+
+        @Override
+        public Optional<T> at(int index) {
+            return index > 0 ? Optional.empty() : Optional.of(value);
+        }
+
+        @Override
+        public final Optional<T> last() {
+            return Optional.of(value);
+        }
+
+        @Override
+        public CQuery<T> reverse() {
+            return this;
+        }
+
+    }
+
     private static final class BIterator<T> implements Iterator<T> {
         
         private final Iterator<T> src;

+ 11 - 0
assira.core/src/main/java/net/ranides/assira/functional/Predicates.java

@@ -34,4 +34,15 @@ public class Predicates {
         boolean test(A a, B b, C c, D d);
     }
 
+    /**
+     *
+     * @author Ranides Atterwim <ranides@gmail.com>
+     */
+    public interface EachPredicate<T> extends Serializable {
+
+        boolean test(int index, T value);
+
+
+    }
+
 }