diff --git a/README.md b/README.md index 0085e03..9b661be 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ and interactive dataflows.** ```groovy dependencies { - compile 'com.github.akarnokd:ixjava:1.0.0-RC3' + compile 'com.github.akarnokd:ixjava:1.0.0-RC5' } ``` @@ -27,7 +27,7 @@ dependencies { ```xml - + ``` diff --git a/gradle.properties b/gradle.properties index fabe516..d4591bd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=1.0.0-RC4 +version=1.0.0-RC5 diff --git a/src/main/java/ix/GroupedIx.java b/src/main/java/ix/GroupedIx.java index c6681fe..1dda83b 100644 --- a/src/main/java/ix/GroupedIx.java +++ b/src/main/java/ix/GroupedIx.java @@ -25,12 +25,23 @@ */ public abstract class GroupedIx extends Ix { + /** + * The group key. + */ protected final K key; + /** + * Constructs a GroupedIx with the given group key. + * @param key the group key + */ public GroupedIx(K key) { this.key = key; } + /** + * Returns this group's key. + * @return the key + */ public final K key() { return key; } diff --git a/src/main/java/ix/Ix.java b/src/main/java/ix/Ix.java index aca9e5b..2911710 100644 --- a/src/main/java/ix/Ix.java +++ b/src/main/java/ix/Ix.java @@ -398,6 +398,58 @@ public static Ix mergeArray(Iterable... sources) { return concatArray(sources); // concat and merge are the same in the Iterable world } + /** + * Merges self-comparable items from an Iterable sequence of Iterable sequences, picking + * the smallest item from all those inner Iterables until all sources complete. + * @param the value type + * @param sources the Iterable sequence of Iterables of self-comparable items + * @return the new Ix instance + * @since 1.0 + */ + public static > Ix orderedMerge(Iterable> sources) { + return orderedMerge(sources, SelfComparator.INSTANCE); + } + + /** + * Merges items from an Iterable sequence of Iterable sequences, picking + * the smallest item (according to a custom comparator) from all those inner + * Iterables until all sources complete. + * @param the value type + * @param sources the Iterable sequence of Iterables + * @param comparator the comparator to compare items and pick the one that returns negative will be picked + * @return the new Ix instance + * @since 1.0 + */ + public static Ix orderedMerge(Iterable> sources, Comparator comparator) { + return new IxOrderedMergeIterable(nullCheck(sources, "sources is null"), nullCheck(comparator, "comparator is null")); + } + + /** + * Merges self-comparable items from an Iterable sequence of Iterable sequences, picking + * the smallest item from all those inner Iterables until all sources complete. + * @param the value type + * @param sources the Iterable sequence of Iterables of self-comparable items + * @return the new Ix instance + * @since 1.0 + */ + public static > Ix orderedMergeArray(Iterable... sources) { + return orderedMergeArray(SelfComparator.INSTANCE, sources); + } + + /** + * Merges items from an array of Iterable sequences, picking + * the smallest item (according to a custom comparator) from all those inner + * Iterables until all sources complete. + * @param the value type + * @param sources the Iterable sequence of Iterables + * @param comparator the comparator to compare items and pick the one that returns negative will be picked + * @return the new Ix instance + * @since 1.0 + */ + public static Ix orderedMergeArray(Comparator comparator, Iterable... sources) { + return new IxOrderedMergeArray(nullCheck(sources, "sources is null"), nullCheck(comparator, "comparator is null")); + } + /** * Emits a range of incrementing integer values, starting from {@code start} and * up to {@code count} times. @@ -420,6 +472,43 @@ public static Ix range(int start, int count) { return new IxRange(start, count); } + /** + * Prevents the downstream from calling remove() and throws + * an UnsupportedOperationException instead. + * @return the new Ix instance + * @see #readOnly(boolean) + * @since 1.0 + */ + public final Ix readOnly() { + return new IxReadOnly(this, false); + } + + /** + * Prevents the downstream from calling remove() by optionally + * ignoring it or throwing an UnsupportedOperationException. + * @param silent if true, remove() calls are ignored; if false, + * remove() calls throw an UnsupportedOperationException + * @return the new Ix instance + * @since 1.0 + */ + public final Ix readOnly(boolean silent) { + return new IxReadOnly(this, silent); + } + + /** + * Repeatedly calls the given callable indefinitely and + * emits the returned value. + *

+ * The result's iterator() doesn't support remove(). + * @param the value type + * @param callable the callable to call + * @return the new Ix instance + * @since 1.0 + */ + public static Ix repeatCallable(Callable callable) { + return new IxRepeatCallable(nullCheck(callable, "callable is null")); + } + /** * Repeats the given value indefinitely. *

@@ -738,6 +827,52 @@ public final Ix> buffer(int size, int skip) { return new IxBufferOverlap(this, positive(size, "size"), positive(skip, "skip")); } + /** + * Buffer until an item is encountered for which the predicate returns true, + * triggering a new buffer. + *

Neither the previous nor the next buffer will contain the item that caused the + * split + * @param predicate the predicate called with each item and should return false + * to trigger a new buffer + * @return the new Ix instance + * @see #bufferUntil(IxPredicate) + * @see #bufferWhile(IxPredicate) + * @since 1.0 + */ + public final Ix> bufferSplit(IxPredicate predicate) { + return new IxBufferSplit(this, nullCheck(predicate, "predicate is null")); + } + + /** + * Buffer until an item is encountered after which the predicate returns true + * to start a new buffer. + *

The item will be part of the previous buffer. + * @param predicate the predicate called with each item after the item + * has been added to the current buffer and should return true to start a new buffer + * @return the new Ix instance + * @see #bufferSplit(IxPredicate) + * @see #bufferWhile(IxPredicate) + * @since 1.0 + */ + public final Ix> bufferUntil(IxPredicate predicate) { + return new IxBufferUntil(this, nullCheck(predicate, "predicate is null")); + } + + /** + * Buffer while an item is encountered before which the predicate returns false + * to start a new buffer. + *

The item will be part of the next buffer + * @param predicate the predicate called with each item after the item + * has been added to the current buffer and should return true to start a new buffer + * @return the new Ix instance + * @see #bufferSplit(IxPredicate) + * @see #bufferUntil(IxPredicate) + * @since 1.0 + */ + public final Ix> bufferWhile(IxPredicate predicate) { + return new IxBufferWhile(this, nullCheck(predicate, "predicate is null")); + } + /** * Cast the elements to the specified class. *

@@ -1095,6 +1230,17 @@ public final Ix endWith(T... values) { return concat(this, fromArray(values)); } + /** + * Emit every Nth item only from upstream. + *

Example: Ix.range(1, 5).every(2) will yield {2, 4}. + * @param nth how many items to skip + 1 + * @return the new Ix instance + * @since 1.0 + */ + public final Ix every(int nth) { + return new IxEvery(this, positive(nth, "nth")); + } + /** * Emits distinct elements from this and the other Iterable which are not * in the other sequence (i.e., (A union B) minus (A intersection B)). diff --git a/src/main/java/ix/IxBufferSplit.java b/src/main/java/ix/IxBufferSplit.java new file mode 100644 index 0000000..e354496 --- /dev/null +++ b/src/main/java/ix/IxBufferSplit.java @@ -0,0 +1,103 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.*; + +/** + * Split into buffers when the predicate returns true and neither + * buffer contains the item. + * + * @param the value type + */ +final class IxBufferSplit extends IxSource> { + + final IxPredicate predicate; + + IxBufferSplit(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator> iterator() { + return new BufferSplitIterator(source.iterator(), predicate); + } + + static final class BufferSplitIterator implements Iterator> { + + final Iterator source; + + final IxPredicate predicate; + + boolean done; + + List buffer; + + BufferSplitIterator(Iterator source, IxPredicate predicate) { + this.source = source; + this.predicate = predicate; + } + + @Override + public boolean hasNext() { + List b = buffer; + if (b == null) { + if (done) { + return false; + } + + b = new ArrayList(); + + Iterator src = source; + while (src.hasNext()) { + T v = src.next(); + + if (predicate.test(v)) { + buffer = b; + return true; + } + + b.add(v); + } + + if (b.isEmpty()) { + done = true; + return false; + } + + buffer = b; + } + return true; + } + + @Override + public List next() { + if (hasNext()) { + List b = buffer; + buffer = null; + return b; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxBufferUntil.java b/src/main/java/ix/IxBufferUntil.java new file mode 100644 index 0000000..6a1e72c --- /dev/null +++ b/src/main/java/ix/IxBufferUntil.java @@ -0,0 +1,104 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.*; + +/** + * Split into buffers when the predicate returns true and neither + * buffer contains the item. + * + * @param the value type + */ +final class IxBufferUntil extends IxSource> { + + final IxPredicate predicate; + + IxBufferUntil(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator> iterator() { + return new BufferSplitIterator(source.iterator(), predicate); + } + + static final class BufferSplitIterator implements Iterator> { + + final Iterator source; + + final IxPredicate predicate; + + boolean done; + + List buffer; + + BufferSplitIterator(Iterator source, IxPredicate predicate) { + this.source = source; + this.predicate = predicate; + } + + @Override + public boolean hasNext() { + List b = buffer; + if (b == null) { + if (done) { + return false; + } + + b = new ArrayList(); + + Iterator src = source; + while (src.hasNext()) { + T v = src.next(); + + b.add(v); + + if (predicate.test(v)) { + buffer = b; + return true; + } + } + + if (b.isEmpty()) { + done = true; + return false; + } + + buffer = b; + done = true; + } + return true; + } + + @Override + public List next() { + if (hasNext()) { + List b = buffer; + buffer = null; + return b; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxBufferWhile.java b/src/main/java/ix/IxBufferWhile.java new file mode 100644 index 0000000..af28b81 --- /dev/null +++ b/src/main/java/ix/IxBufferWhile.java @@ -0,0 +1,111 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.*; + +/** + * Buffer while the predicate returns true. + * + * @param the value type + */ +final class IxBufferWhile extends IxSource> { + + final IxPredicate predicate; + + IxBufferWhile(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator> iterator() { + return new BufferSplitIterator(source.iterator(), predicate); + } + + static final class BufferSplitIterator implements Iterator> { + + final Iterator source; + + final IxPredicate predicate; + + boolean done; + + List buffer; + + List next; + + BufferSplitIterator(Iterator source, IxPredicate predicate) { + this.source = source; + this.predicate = predicate; + } + + @Override + public boolean hasNext() { + List b = buffer; + if (b == null) { + if (done) { + return false; + } + + b = next; + if (b == null) { + b = new ArrayList(); + } + + Iterator src = source; + while (src.hasNext()) { + T v = src.next(); + + if (!predicate.test(v)) { + buffer = b; + b = new ArrayList(); + b.add(v); + next = b; + return true; + } + + b.add(v); + } + + if (b.isEmpty()) { + done = true; + return false; + } + + buffer = b; + done = true; + } + return true; + } + + @Override + public List next() { + if (hasNext()) { + List b = buffer; + buffer = null; + return b; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxEvery.java b/src/main/java/ix/IxEvery.java new file mode 100644 index 0000000..7c510a2 --- /dev/null +++ b/src/main/java/ix/IxEvery.java @@ -0,0 +1,95 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.*; + +/** + * Emits every Nth item from upstream. + * + * @param the value type + */ +final class IxEvery extends IxSource { + + final int nth; + + IxEvery(Iterable source, int nth) { + super(source); + this.nth = nth; + } + + @Override + public Iterator iterator() { + return new EveryIterator(source.iterator(), nth); + } + + static final class EveryIterator implements Iterator { + + final Iterator source; + + final int nth; + + boolean done; + + boolean hasValue; + + EveryIterator(Iterator it, int nth) { + this.source = it; + this.nth = nth; + } + + @Override + public boolean hasNext() { + if (done) { + return false; + } + if (!hasValue) { + int i = nth - 1; + + Iterator src = source; + + while (i != 0 && src.hasNext()) { + src.next(); + i--; + } + + if (src.hasNext()) { + hasValue = true; + return true; + } + + done = true; + return false; + } + return true; + } + + @Override + public T next() { + if (hasNext()) { + hasValue = false; + return source.next(); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + source.remove(); + } + } +} diff --git a/src/main/java/ix/IxOrderedMergeArray.java b/src/main/java/ix/IxOrderedMergeArray.java new file mode 100644 index 0000000..ce895fa --- /dev/null +++ b/src/main/java/ix/IxOrderedMergeArray.java @@ -0,0 +1,142 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.*; + +/** + * Merges an array of Iterable items by picking the smallest from them + * with the help of a Comparator. + * + * @param the value type + */ +final class IxOrderedMergeArray extends Ix { + + final Iterable[] sources; + + final Comparator comparator; + + IxOrderedMergeArray(Iterable[] sources, Comparator comparator) { + this.sources = sources; + this.comparator = comparator; + } + + @Override + public Iterator iterator() { + Iterable[] all = sources; + int n = all.length; + @SuppressWarnings("unchecked") + Iterator[] srcs = new Iterator[n]; + for (int i = 0; i < n; i++) { + srcs[i] = all[i].iterator(); + } + return new OrderedMergeIterator(srcs, n, comparator); + } + + static final class OrderedMergeIterator implements Iterator { + + final Iterator[] sources; + + final Comparator comparator; + + final int n; + + final Object[] latest; + + static final Object EMPTY = new Object(); + + static final Object DONE = new Object(); + + boolean done; + + int index; + + OrderedMergeIterator(Iterator[] sources, int n, Comparator comparator) { + this.sources = sources; + this.n = n; + this.latest = new Object[n]; + Arrays.fill(latest, EMPTY); + this.comparator = comparator; + this.index = -1; + } + + @SuppressWarnings("unchecked") + @Override + public boolean hasNext() { + int i = index; + if (i < 0) { + if (done) { + return false; + } + int count = n; + Object[] vs = latest; + int d = 0; + int f = -1; + T min = null; + for (int j = 0; j < count; j++) { + Object o = vs[j]; + if (o == DONE) { + d++; + continue; + } else + if (o == EMPTY) { + Iterator src = sources[j]; + if (src.hasNext()) { + o = src.next(); + vs[j] = o; + } else { + d++; + vs[j] = DONE; + continue; + } + } + + if (f < 0 || comparator.compare(min, (T)o) > 0) { + f = j; + min = (T)o; + } + } + + if (d == count) { + done = true; + return false; + } + + index = f; + } + return true; + } + + @Override + public T next() { + if (hasNext()) { + int i = index; + index = -1; + @SuppressWarnings("unchecked") + T v = (T)latest[i]; + latest[i] = EMPTY; + return v; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxOrderedMergeIterable.java b/src/main/java/ix/IxOrderedMergeIterable.java new file mode 100644 index 0000000..d5af595 --- /dev/null +++ b/src/main/java/ix/IxOrderedMergeIterable.java @@ -0,0 +1,55 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.*; + +import ix.IxOrderedMergeArray.OrderedMergeIterator; + +/** + * Merges an array of Iterable items by picking the smallest from them + * with the help of a Comparator. + * + * @param the value type + */ +final class IxOrderedMergeIterable extends Ix { + + final Iterable> sources; + + final Comparator comparator; + + IxOrderedMergeIterable(Iterable> sources, Comparator comparator) { + this.sources = sources; + this.comparator = comparator; + } + + @Override + public Iterator iterator() { + @SuppressWarnings("unchecked") + Iterator[] srcs = new Iterator[8]; + int n = 0; + + for (Iterable iter : sources) { + if (n == srcs.length) { + srcs = Arrays.copyOf(srcs, n + (n >> 2)); + } + srcs[n++] = iter.iterator(); + } + + return new OrderedMergeIterator(srcs, n, comparator); + } +} diff --git a/src/main/java/ix/IxReadOnly.java b/src/main/java/ix/IxReadOnly.java new file mode 100644 index 0000000..6850d90 --- /dev/null +++ b/src/main/java/ix/IxReadOnly.java @@ -0,0 +1,90 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.Iterator; + +/** + * Suppress or throw when the remove() is called. + * + * @param the value type + */ +final class IxReadOnly extends IxSource { + + final boolean silent; + + IxReadOnly(Iterable source, boolean silent) { + super(source); + this.silent = silent; + } + + @Override + public Iterator iterator() { + if (silent) { + return new ReadOnlySilentIterator(source.iterator()); + } + return new ReadOnlyThrowingIterator(source.iterator()); + } + + static final class ReadOnlySilentIterator implements Iterator { + + final Iterator source; + + ReadOnlySilentIterator(Iterator source) { + this.source = source; + } + + @Override + public boolean hasNext() { + return source.hasNext(); + } + + @Override + public T next() { + return source.next(); + } + + @Override + public void remove() { + // deliberately ignored + } + } + + static final class ReadOnlyThrowingIterator implements Iterator { + + final Iterator source; + + ReadOnlyThrowingIterator(Iterator source) { + this.source = source; + } + + @Override + public boolean hasNext() { + return source.hasNext(); + } + + @Override + public T next() { + return source.next(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxRepeat.java b/src/main/java/ix/IxRepeat.java index c06f8f0..a30b998 100644 --- a/src/main/java/ix/IxRepeat.java +++ b/src/main/java/ix/IxRepeat.java @@ -18,7 +18,7 @@ import java.util.Iterator; -final class IxRepeat extends Ix { +final class IxRepeat extends Ix implements Iterator { final T value; @@ -28,30 +28,21 @@ final class IxRepeat extends Ix { @Override public Iterator iterator() { - return new RepeatIterator(value); + return this; } - static final class RepeatIterator implements Iterator { - - final T value; - - RepeatIterator(T value) { - this.value = value; - } - - @Override - public boolean hasNext() { - return true; - } + @Override + public boolean hasNext() { + return true; + } - @Override - public T next() { - return value; - } + @Override + public T next() { + return value; + } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } + @Override + public void remove() { + throw new UnsupportedOperationException(); } } diff --git a/src/main/java/ix/IxRepeatCallable.java b/src/main/java/ix/IxRepeatCallable.java new file mode 100644 index 0000000..1587466 --- /dev/null +++ b/src/main/java/ix/IxRepeatCallable.java @@ -0,0 +1,54 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.Iterator; +import java.util.concurrent.Callable; + +/** + * Repeatedly call a Callable indefinitely. + * + * @param the value type + */ +final class IxRepeatCallable extends Ix implements Iterator { + + final Callable callable; + + IxRepeatCallable(Callable callable) { + this.callable = callable; + } + + @Override + public Iterator iterator() { + return this; + } + + @Override + public boolean hasNext() { + return true; + } + + @Override + public T next() { + return checkedCall(callable); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/test/java/ix/BufferPredicateTest.java b/src/test/java/ix/BufferPredicateTest.java new file mode 100644 index 0000000..c71f4dd --- /dev/null +++ b/src/test/java/ix/BufferPredicateTest.java @@ -0,0 +1,153 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.*; + +import org.junit.Test; + +public class BufferPredicateTest { + + @SuppressWarnings("unchecked") + @Test + public void splitNormal() { + Ix> source = Ix.fromArray(1, 2, 10, 3, 10, 4) + .bufferSplit(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(3), Arrays.asList(4)); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void splitNormalEmpty() { + Ix> source = Ix.fromArray(1, 2, 10, 10) + .bufferSplit(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList()); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void whileNormal() { + Ix> source = Ix.fromArray(1, 2, 10, 3, 10, 4) + .bufferWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v != 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(10, 3), Arrays.asList(10, 4)); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void whileNormalEmpty() { + Ix> source = Ix.fromArray(1, 2, 10, 10) + .bufferWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v != 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(10), Arrays.asList(10)); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void untilNormal() { + Ix> source = Ix.fromArray(1, 2, 10, 3, 10, 4) + .bufferUntil(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2, 10), Arrays.asList(3, 10), Arrays.asList(4)); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void untilNormalEmpty() { + Ix> source = Ix.fromArray(1, 2, 10, 10) + .bufferUntil(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2, 10), Arrays.asList(10)); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void splitEmpty() { + Ix> source = Ix.empty().bufferSplit(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source); + } + + @SuppressWarnings("unchecked") + @Test + public void whileEmpty() { + Ix> source = Ix.empty().bufferWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v != 10; + } + }); + + IxTestHelper.assertValues(source); + } + + @SuppressWarnings("unchecked") + @Test + public void untilEmpty() { + Ix> source = Ix.empty().bufferUntil(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source); + } +} diff --git a/src/test/java/ix/EveryTest.java b/src/test/java/ix/EveryTest.java new file mode 100644 index 0000000..b8f2b06 --- /dev/null +++ b/src/test/java/ix/EveryTest.java @@ -0,0 +1,62 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.*; + +import org.junit.*; + +public class EveryTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 5).every(2); + + IxTestHelper.assertValues(source, 2, 4); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normal2() { + Ix source = Ix.range(1, 5).every(1); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normal3() { + Ix source = Ix.range(1, 5).every(10); + + IxTestHelper.assertValues(source); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void remove() { + List list = new ArrayList(); + list.add(1); + list.add(2); + list.add(3); + list.add(4); + list.add(5); + + Ix.from(list).every(2).removeAll(); + + Assert.assertEquals(Arrays.asList(1, 3, 5), list); + } +} diff --git a/src/test/java/ix/OrderedMergeTest.java b/src/test/java/ix/OrderedMergeTest.java new file mode 100644 index 0000000..4038293 --- /dev/null +++ b/src/test/java/ix/OrderedMergeTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.Comparator; + +import org.junit.Test; + +public class OrderedMergeTest { + + @Test + public void normalArray() { + @SuppressWarnings("unchecked") + Ix source = Ix.orderedMergeArray(Ix.fromArray(1, 3), Ix.fromArray(2, 4, 5)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalIterable() { + @SuppressWarnings("unchecked") + Ix source = Ix.orderedMerge(Ix.fromArray(Ix.fromArray(1, 3), Ix.fromArray(2, 4, 5))); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + IxTestHelper.assertNoRemove(source); + } + + @Test + @SuppressWarnings("unchecked") + public void firstEmptyArray() { + Ix source = Ix.orderedMergeArray(Ix.empty(), Ix.fromArray(2, 4, 5)); + + IxTestHelper.assertValues(source, 2, 4, 5); + } + + @Test + @SuppressWarnings("unchecked") + public void secondEmptyArray() { + Ix source = Ix.orderedMergeArray(Ix.fromArray(1, 3), Ix.empty()); + + IxTestHelper.assertValues(source, 1, 3); + } + + @Test + @SuppressWarnings("unchecked") + public void bothEmptyArray() { + Ix source = Ix.orderedMergeArray(Ix.empty(), Ix.empty()); + + IxTestHelper.assertValues(source); + } + + @Test + public void comparatorArray() { + @SuppressWarnings("unchecked") + Ix source = Ix.orderedMergeArray( + new Comparator() { + @Override + public int compare(Integer o1, Integer o2) { + return o2.compareTo(o1); + } + }, + Ix.fromArray(3, 1), Ix.fromArray(5, 4, 2)); + + IxTestHelper.assertValues(source, 5, 4, 3, 2, 1); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void comparatorIterable() { + @SuppressWarnings("unchecked") + Ix source = Ix.orderedMerge(Ix.fromArray(Ix.fromArray(3, 1), Ix.fromArray(5, 4, 2)), + new Comparator() { + @Override + public int compare(Integer o1, Integer o2) { + return o2.compareTo(o1); + } + } + ); + + IxTestHelper.assertValues(source, 5, 4, 3, 2, 1); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void lotsOfIterables() { + Ix source = Ix.orderedMerge(Ix.repeatValue(Ix.just(1), 30)).sumInt(); + + IxTestHelper.assertValues(source, 30); + } +} diff --git a/src/test/java/ix/ReadOnlyTest.java b/src/test/java/ix/ReadOnlyTest.java new file mode 100644 index 0000000..98384ab --- /dev/null +++ b/src/test/java/ix/ReadOnlyTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ix; + +import java.util.*; + +import org.junit.*; + +public class ReadOnlyTest { + + @Test + public void normal() { + List list = new ArrayList(); + list.add(1); + list.add(2); + list.add(3); + + Ix source = Ix.from(list).readOnly(); + + IxTestHelper.assertValues(source, 1, 2, 3); + IxTestHelper.assertNoRemove(source); + + Assert.assertEquals(3, list.size()); + } + + @Test + public void normalSilent() { + List list = new ArrayList(); + list.add(1); + list.add(2); + list.add(3); + + Ix source = Ix.from(list).readOnly(true); + + IxTestHelper.assertValues(source, 1, 2, 3); + + source.removeAll(); + + Assert.assertEquals(3, list.size()); + + IxTestHelper.assertValues(source, 1, 2, 3); + } +} diff --git a/src/test/java/ix/RepeatTest.java b/src/test/java/ix/RepeatTest.java index 0f9da8a..e3c8ee7 100644 --- a/src/test/java/ix/RepeatTest.java +++ b/src/test/java/ix/RepeatTest.java @@ -16,6 +16,8 @@ package ix; +import java.util.concurrent.Callable; + import org.junit.Test; public class RepeatTest { @@ -237,4 +239,19 @@ public boolean getAsBoolean() { IxTestHelper.assertNoRemove(source); } + + @Test + public void repeatCallable() { + Ix source = Ix.repeatCallable(new Callable() { + @Override + public Integer call() throws Exception { + return 1; + } + }) + .take(5); + + IxTestHelper.assertValues(source, 1, 1, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } }