GROOVY-5936: provide an iterator backed implementation for Iterator DGM dropRight rather than convert to a list
diff --git a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index 839c7e8..b61f3be 100644
--- a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -9971,8 +9971,49 @@
* @since 2.4.0
*/
public static <T> Iterator<T> dropRight(Iterator<T> self, int num) {
- List<T> result = dropRight(toList(self), num);
- return result.listIterator();
+ if (num <= 0) {
+ return self;
+ }
+ return new DropRightIterator<T>(self, num);
+ }
+
+ private static final class DropRightIterator<E> implements Iterator<E> {
+ private final Iterator<E> delegate;
+ private final LinkedList<E> discards;
+ private boolean exhausted;
+ private int num;
+
+ private DropRightIterator(Iterator<E> delegate, int num) {
+ this.delegate = delegate;
+ this.num = num;
+ discards = new LinkedList<E>();
+ advance();
+ }
+
+ public boolean hasNext() {
+ return !exhausted;
+ }
+
+ public E next() {
+ if (exhausted) throw new NoSuchElementException();
+ E result = discards.removeFirst();
+ advance();
+ return result;
+ }
+
+ public void remove() {
+ if (exhausted) throw new NoSuchElementException();
+ delegate.remove();
+ }
+
+ private void advance() {
+ while (discards.size() <= num && !exhausted) {
+ exhausted = !delegate.hasNext();
+ if (!exhausted) {
+ discards.add(delegate.next());
+ }
+ }
+ }
}
/**
diff --git a/src/test/groovy/GroovyMethodsTest.groovy b/src/test/groovy/GroovyMethodsTest.groovy
index cf55750..267f4d1 100644
--- a/src/test/groovy/GroovyMethodsTest.groovy
+++ b/src/test/groovy/GroovyMethodsTest.groovy
@@ -1276,6 +1276,15 @@
assert items.drop( 4 ).collect { it } == [ 5 ]
a = 1
assert items.drop( 5 ).collect { it } == []
+
+ a = 1
+ assert items.dropRight( 0 ).collect { it } == [ 1, 2, 3, 4, 5 ]
+ a = 1
+ assert items.dropRight( 2 ).collect { it } == [ 1, 2, 3 ]
+ a = 1
+ assert items.dropRight( 4 ).collect { it } == [ 1 ]
+ a = 1
+ assert items.dropRight( 5 ).collect { it } == []
}
void testIterableDrop() {