Skip to content

Commit

Permalink
some TODOs in Iterator fixed #487
Browse files Browse the repository at this point in the history
  • Loading branch information
ruslansennov committed Sep 2, 2015
1 parent 64a872d commit 2c9f6c0
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 52 deletions.
18 changes: 5 additions & 13 deletions src/main/java/javaslang/collection/HashSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public HashSet<T> filter(Predicate<? super T> predicate) {

@Override
public Option<T> findLast(Predicate<? super T> predicate) {
throw new UnsupportedOperationException("TODO");
return findFirst(predicate);
}

@Override
Expand All @@ -212,7 +212,7 @@ public HashSet<Object> flatten() {

@Override
public <U> U foldRight(U zero, BiFunction<? super T, ? super U, ? extends U> f) {
throw new UnsupportedOperationException("TODO");
return foldLeft(zero, (u, t) -> f.apply(t, u));
}

@Override
Expand Down Expand Up @@ -292,16 +292,8 @@ public String mkString(CharSequence delimiter,
@Override
public Tuple2<HashSet<T>, HashSet<T>> partition(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
HashSet<T> first = HashSet.empty();
HashSet<T> second = HashSet.empty();
for (T t : this) {
if (predicate.test(t)) {
first = first.add(t);
} else {
second = second.add(t);
}
}
return Tuple.of(first, second);
final Tuple2<Iterator<T>, Iterator<T>> p = iterator().partition(predicate);
return Tuple.of(HashSet.ofAll(p._1), HashSet.ofAll(p._2));
}

@Override
Expand All @@ -315,7 +307,7 @@ public HashSet<T> peek(Consumer<? super T> action) {

@Override
public T reduceRight(BiFunction<? super T, ? super T, ? extends T> op) {
throw new UnsupportedOperationException("TODO");
return reduceLeft(op);
}

@Override
Expand Down
159 changes: 152 additions & 7 deletions src/main/java/javaslang/collection/Iterator.java
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,104 @@ public Long next() {
}
}

// TODO: add static factory methods similar to Stream.from, Stream.gen, ...
/**
* Returns an infinitely iterator of int values starting from {@code from}.
* <p>
* The {@code Iterator} extends to {@code Integer.MIN_VALUE} when passing {@code Integer.MAX_VALUE}.
*
* @param value a start int value
* @return a new {@code Iterator} of int values starting from {@code from}
*/
static Iterator<Integer> from(int value) {
return new AbstractIterator<Integer>() {
private int next = value;

@Override
public boolean hasNext() {
return true;
}

@Override
public Integer next() {
return next++;
}
};
}

/**
* Returns an infinitely iterator of long values starting from {@code from}.
* <p>
* The {@code Iterator} extends to {@code Long.MIN_VALUE} when passing {@code Long.MAX_VALUE}.
*
* @param value a start long value
* @return a new {@code Iterator} of long values starting from {@code from}
*/
static Iterator<Long> from(long value) {
return new AbstractIterator<Long>() {
private long next = value;

@Override
public boolean hasNext() {
return true;
}

@Override
public Long next() {
return next++;
}
};
}

/**
* Generates an infinitely iterator using a value Supplier.
*
* @param supplier A Supplier of iterator values
* @param <T> value type
* @return A new {@code Iterator}
*/
@SuppressWarnings("unchecked")
static <T> Iterator<T> gen(Supplier<? extends T> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return new AbstractIterator<T>() {
@Override
public boolean hasNext() {
return true;
}

@Override
public T next() {
return supplier.get();
}
};
}

/**
* Generates an infinitely iterator using a function to calculate the next value
* based on the previous.
*
* @param seed The first value in the iterator
* @param f A function to calculate the next value based on the previous
* @param <T> value type
* @return A new {@code Iterator}
*/
static <T> Iterator<T> gen(T seed, Function<? super T, ? extends T> f) {
Objects.requireNonNull(f, "f is null");
return new AbstractIterator<T>() {
T next = seed;

@Override
public boolean hasNext() {
return true;
}

@Override
public T next() {
T result = next;
next = f.apply(next);
return result;
}
};
}

@Override
default Iterator<T> clear() {
Expand Down Expand Up @@ -1095,8 +1192,14 @@ public U next() {
@Override
default Tuple2<Iterator<T>, Iterator<T>> partition(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
// TODO
throw new UnsupportedOperationException("TODO");
if (!hasNext()) {
return Tuple.of(empty(), empty());
} else {
final Stream<T> that = Stream.ofAll(this);
final Iterator<T> first = that.iterator().filter(predicate);
final Iterator<T> second = that.iterator().filter(predicate.negate());
return Tuple.of(first, second);
}
}

@Override
Expand Down Expand Up @@ -1125,11 +1228,26 @@ public T next() {
}
}

@Override
default T reduceLeft(BiFunction<? super T, ? super T, ? extends T> op) {
Objects.requireNonNull(op, "op is null");
if (isEmpty()) {
throw new NoSuchElementException("reduceLeft on Nil");
} else {
Stream<T> stream = Stream.ofAll(this);
return stream.tail().foldLeft(stream.head(), op::apply);
}
}

@Override
default T reduceRight(BiFunction<? super T, ? super T, ? extends T> op) {
Objects.requireNonNull(op, "op is null");
// TODO
throw new UnsupportedOperationException("TODO");
if (isEmpty()) {
throw new NoSuchElementException("reduceLeft on Nil");
} else {
Stream<T> reversed = Stream.ofAll(this).reverse();
return reversed.tail().foldLeft(reversed.head(), (xs, x) -> op.apply(x, xs));
}
}

@Override
Expand Down Expand Up @@ -1334,8 +1452,35 @@ public T next() {

@Override
default Iterator<T> takeRight(int n) {
// TODO
throw new UnsupportedOperationException("TODO");
if (n <= 0) {
return empty();
} else {
final Iterator<T> that = this;
return new Iterator<T>() {
private Queue<T> queue = Queue.empty();

@Override
public boolean hasNext() {
while (that.hasNext()) {
queue = queue.append(that.next());
if(queue.length() > n) {
queue = queue.dequeue()._2;
}
}
return queue.length() > 0;
}

@Override
public T next() {
if (!hasNext()) {
EMPTY.next();
}
final Tuple2<T, Queue<T>> t = queue.dequeue();
queue = t._2;
return t._1;
}
};
}
}

@Override
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/javaslang/collection/Seq.java
Original file line number Diff line number Diff line change
Expand Up @@ -726,8 +726,7 @@ default T reduceRight(BiFunction<? super T, ? super T, ? extends T> op) {
if (isEmpty()) {
throw new NoSuchElementException("reduceRight on Nil");
} else {
final Seq<T> reversed = reverse();
return reversed.tail().foldLeft(reversed.head(), (xs, x) -> op.apply(x, xs));
return iterator().reduceRight(op);
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/main/java/javaslang/collection/Stream.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ static <T> Collector<T, ArrayList<T>, Stream<T>> collector() {
* @return a new Stream of int values starting from {@code from}
*/
static Stream<Integer> from(int value) {
return new Cons<>(() -> value, () -> from(value + 1));
return Stream.ofAll(Iterator.from(value));
}

/**
Expand All @@ -135,7 +135,7 @@ static Stream<Integer> from(int value) {
* @return a new Stream of long values starting from {@code from}
*/
static Stream<Long> from(long value) {
return new Cons<>(() -> value, () -> from(value + 1));
return Stream.ofAll(Iterator.from(value));
}

/**
Expand All @@ -148,7 +148,7 @@ static Stream<Long> from(long value) {
@SuppressWarnings("unchecked")
static <T> Stream<T> gen(Supplier<? extends T> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return new Cons<>((Supplier<T>) supplier, () -> gen(supplier));
return Stream.ofAll(Iterator.gen(supplier));
}

/**
Expand All @@ -162,7 +162,7 @@ static <T> Stream<T> gen(Supplier<? extends T> supplier) {
*/
static <T> Stream<T> gen(T seed, Function<? super T, ? extends T> f) {
Objects.requireNonNull(f, "f is null");
return new Stream.Cons<>(() -> seed, () -> gen(f.apply(seed), f));
return Stream.ofAll(Iterator.gen(seed, f));
}

/**
Expand Down Expand Up @@ -1150,7 +1150,7 @@ default Stream<T> takeRight(int n) {
} else if (length() <= n) {
return this;
} else {
return reverse().take(n).reverse();
return Stream.ofAll(iterator().takeRight(n));
}
}

Expand Down
25 changes: 0 additions & 25 deletions src/test/java/javaslang/collection/HashSetTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -345,16 +345,6 @@ public void shouldFoldRightNil() {
// TODO
}

@Override
public void shouldThrowWhenReduceRightNullOperator() {
throw new NullPointerException(); // TODO
}

@Override
public void shouldThrowWhenReduceRightNil() {
throw new NoSuchElementException(); // TODO
}

@Override
public void shouldFindLastOfNil() {
// TODO
Expand Down Expand Up @@ -385,16 +375,6 @@ public void shouldSerializeDeserializeNonNil() {
// TODO
}

@Override
public void shouldPartitionIntsInOddAndEvenHavingOddAndEventNumbers() {
// TODO
}

@Override
public void shouldPartitionIntsInOddAndEvenHavingOnlyEvenNumbers() {
// TODO
}

@Override
public void shouldSpanNonNil() {
// TODO
Expand All @@ -410,11 +390,6 @@ public void shouldReturnSomeTailWhenCallingTailOptionOnNonNil() {
// TODO
}

@Override
public void shouldPartitionIntsInOddAndEvenHavingOnlyOddNumbers() {
// TODO
}

@Override
public void shouldSlideNonNilBySize1() {
// TODO
Expand Down
41 changes: 41 additions & 0 deletions src/test/java/javaslang/collection/IteratorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,45 @@ boolean isThisLazyJavaslangObject() {
int getPeekNonNilPerformingAnAction() {
return 3;
}

// -- static from(int)

@Test
public void shouldGenerateIntStream() {
assertThat(Iterator.from(-1).take(3)).isEqualTo(Iterator.of(-1, 0, 1));
}

@Test
public void shouldGenerateTerminatingIntStream() {
//noinspection NumericOverflow
assertThat(Iterator.from(Integer.MAX_VALUE).take(2)).isEqualTo(Iterator.of(Integer.MAX_VALUE, Integer.MAX_VALUE + 1));
}

// -- static from(long)

@Test
public void shouldGenerateLongStream() {
assertThat(Iterator.from(-1L).take(3)).isEqualTo(Iterator.of(-1L, 0L, 1L));
}

@Test
public void shouldGenerateTerminatingLongStream() {
//noinspection NumericOverflow
assertThat(Iterator.from(Long.MAX_VALUE).take(2)).isEqualTo(Iterator.of(Long.MAX_VALUE, Long.MAX_VALUE + 1));
}

// -- static gen(Supplier)

@Test
public void shouldGenerateInfiniteStreamBasedOnSupplier() {
assertThat(Iterator.gen(() -> 1).take(13).reduce((i, j) -> i + j)).isEqualTo(13);
}

// -- static gen(T, Function)

@Test
public void shouldGenerateInfiniteStreamBasedOnSupplierWithAccessToPreviousValue() {
assertThat(Iterator.gen(2, (i) -> i + 2).take(3).reduce((i, j) -> i + j)).isEqualTo(12);
}

}

0 comments on commit 2c9f6c0

Please sign in to comment.