You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/12/19 07:32:10 UTC

groovy git commit: GROOVY-8406: Various DefaultGroovyMethods missing Array variants resulting in no type inference

Repository: groovy
Updated Branches:
  refs/heads/master c89393104 -> 047c8f29b


GROOVY-8406: Various DefaultGroovyMethods missing Array variants resulting in no type inference


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/047c8f29
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/047c8f29
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/047c8f29

Branch: refs/heads/master
Commit: 047c8f29b1f7a1a98b2b003e4d09c1cef05feb0e
Parents: c893931
Author: paulk <pa...@asert.com.au>
Authored: Tue Dec 12 01:14:26 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Tue Dec 19 17:31:11 2017 +1000

----------------------------------------------------------------------
 .../groovy/runtime/DefaultGroovyMethods.java    | 1012 +++++++++++++-----
 .../stc/ClosureParamTypeInferenceSTCTest.groovy |   98 +-
 2 files changed, 856 insertions(+), 254 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/047c8f29/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index eec02af..3037fea 100644
--- a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -2445,19 +2445,13 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * def greaterThanTwo = list.every { it > 2 }
      * </pre>
      *
-     * @param self    the object over which we iterate
-     * @param closure the closure predicate used for matching
+     * @param self      the object over which we iterate
+     * @param predicate the closure predicate used for matching
      * @return true if every iteration of the object matches the closure predicate
      * @since 1.0
      */
-    public static boolean every(Object self, Closure closure) {
-        BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
-        for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
-            if (!bcw.call(iter.next())) {
-                return false;
-            }
-        }
-        return true;
+    public static boolean every(Object self, Closure predicate) {
+        return every(InvokerHelper.asIterator(self), predicate);
     }
 
     /**
@@ -2468,13 +2462,13 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * def greaterThanTwo = list.iterator().every { it > 2 }
      * </pre>
      *
-     * @param self    the iterator over which we iterate
-     * @param closure the closure predicate used for matching
+     * @param self      the iterator over which we iterate
+     * @param predicate the closure predicate used for matching
      * @return true if every iteration of the object matches the closure predicate
      * @since 2.3.0
      */
-    public static <T> boolean every(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
-        BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
+    public static <T> boolean every(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure predicate) {
+        BooleanClosureWrapper bcw = new BooleanClosureWrapper(predicate);
         while (self.hasNext()) {
             if (!bcw.call(self.next())) {
                 return false;
@@ -2485,19 +2479,32 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
 
     /**
      * Used to determine if the given predicate closure is valid (i.e. returns
+     * <code>true</code> for all items in this Array).
+     *
+     * @param self      an Array
+     * @param predicate the closure predicate used for matching
+     * @return true if every element of the Array matches the closure predicate
+     * @since 2.5.0
+     */
+    public static <T> boolean every(T[] self, @ClosureParams(FirstParam.Component.class) Closure predicate) {
+        return every(new ArrayIterator<T>(self), predicate);
+    }
+
+    /**
+     * Used to determine if the given predicate closure is valid (i.e. returns
      * <code>true</code> for all items in this iterable).
      * A simple example for a list:
      * <pre>def list = [3,4,5]
      * def greaterThanTwo = list.every { it > 2 }
      * </pre>
      *
-     * @param self    the iterable over which we iterate
-     * @param closure the closure predicate used for matching
+     * @param self      the iterable over which we iterate
+     * @param predicate the closure predicate used for matching
      * @return true if every iteration of the object matches the closure predicate
      * @since 2.3.0
      */
-    public static <T> boolean every(Iterable<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
-        return every(self.iterator(), closure);
+    public static <T> boolean every(Iterable<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure predicate) {
+        return every(self.iterator(), predicate);
     }
 
     /**
@@ -2510,13 +2517,13 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * assert !map.every { key, value -> value instanceof Integer }
      * assert map.every { entry -> entry.value instanceof Number }</pre>
      *
-     * @param self    the map over which we iterate
-     * @param closure the 1 or 2 arg Closure predicate used for matching
+     * @param self      the map over which we iterate
+     * @param predicate the 1 or 2 arg Closure predicate used for matching
      * @return true if every entry of the map matches the closure predicate
      * @since 1.5.0
      */
-    public static <K, V> boolean every(Map<K, V> self, @ClosureParams(value=MapEntryOrKeyValue.class) Closure closure) {
-        BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
+    public static <K, V> boolean every(Map<K, V> self, @ClosureParams(value = MapEntryOrKeyValue.class) Closure predicate) {
+        BooleanClosureWrapper bcw = new BooleanClosureWrapper(predicate);
         for (Map.Entry<K, V> entry : self.entrySet()) {
             if (!bcw.callForMap(entry)) {
                 return false;
@@ -2536,13 +2543,12 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * </pre>
      *
      * @param self the object over which we iterate
-     * @return true if every item in the collection matches the closure
-     *         predicate
+     * @return true if every item in the collection matches satisfies Groovy truth
      * @since 1.5.0
      */
     public static boolean every(Object self) {
         BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker();
-        for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
+        for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext(); ) {
             if (!bmi.convertToBoolean(iter.next())) {
                 return false;
             }
@@ -2558,17 +2564,13 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * assert ![1, 2, 3].any { it > 3 }
      * </pre>
      *
-     * @param self    the object over which we iterate
-     * @param closure the closure predicate used for matching
-     * @return true   if any iteration for the object matches the closure predicate
+     * @param self      the object over which we iterate
+     * @param predicate the closure predicate used for matching
+     * @return true if any iteration for the object matches the closure predicate
      * @since 1.0
      */
-    public static boolean any(Object self, Closure closure) {
-        BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
-        for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
-            if (bcw.call(iter.next())) return true;
-        }
-        return false;
+    public static boolean any(Object self, Closure predicate) {
+        return any(InvokerHelper.asIterator(self), predicate);
     }
 
     /**
@@ -2579,15 +2581,15 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * assert ![1, 2, 3].iterator().any { it > 3 }
      * </pre>
      *
-     * @param self    the iterator over which we iterate
-     * @param closure the closure predicate used for matching
-     * @return true   if any iteration for the object matches the closure predicate
+     * @param self      the iterator over which we iterate
+     * @param predicate the closure predicate used for matching
+     * @return true if any iteration for the object matches the closure predicate
      * @since 1.0
      */
-    public static <T> boolean any(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
-        BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
-        for (Iterator iter = self; iter.hasNext();) {
-            if (bcw.call(iter.next())) return true;
+    public static <T> boolean any(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure predicate) {
+        BooleanClosureWrapper bcw = new BooleanClosureWrapper(predicate);
+        while (self.hasNext()) {
+            if (bcw.call(self.next())) return true;
         }
         return false;
     }
@@ -2600,17 +2602,26 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * assert ![1, 2, 3].any { it > 3 }
      * </pre>
      *
-     * @param self    the iterable over which we iterate
-     * @param closure the closure predicate used for matching
-     * @return true   if any iteration for the object matches the closure predicate
+     * @param self      the iterable over which we iterate
+     * @param predicate the closure predicate used for matching
+     * @return true if any iteration for the object matches the closure predicate
      * @since 1.0
      */
-    public static <T> boolean any(Iterable<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
-        BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
-        for (Iterator<T> iter = self.iterator(); iter.hasNext();) {
-            if (bcw.call(iter.next())) return true;
-        }
-        return false;
+    public static <T> boolean any(Iterable<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure predicate) {
+        return any(self.iterator(), predicate);
+    }
+
+    /**
+     * Iterates over the contents of an Array, and checks whether a
+     * predicate is valid for at least one element.
+     *
+     * @param self      the array over which we iterate
+     * @param predicate the closure predicate used for matching
+     * @return true if any iteration for the object matches the closure predicate
+     * @since 2.5.0
+     */
+    public static <T> boolean any(T[] self, @ClosureParams(FirstParam.Component.class) Closure predicate) {
+        return any(new ArrayIterator<T>(self), predicate);
     }
 
     /**
@@ -2624,13 +2635,13 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * assert ![2:3, 4:5, 5:10].any { entry -> entry.key == entry.value * 2 }
      * </pre>
      *
-     * @param self    the map over which we iterate
-     * @param closure the 1 or 2 arg closure predicate used for matching
+     * @param self      the map over which we iterate
+     * @param predicate the 1 or 2 arg closure predicate used for matching
      * @return true if any entry in the map matches the closure predicate
      * @since 1.5.0
      */
-    public static <K, V> boolean any(Map<K, V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure<?> closure) {
-        BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
+    public static <K, V> boolean any(Map<K, V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure<?> predicate) {
+        BooleanClosureWrapper bcw = new BooleanClosureWrapper(predicate);
         for (Map.Entry<K, V> entry : self.entrySet()) {
             if (bcw.callForMap(entry)) {
                 return true;
@@ -3354,6 +3365,20 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
     }
 
     /**
+     * Iterates through this aggregate Object transforming each item into a new value using Closure.IDENTITY
+     * as a transformer, basically returning a list of items copied from the original object.
+     * <pre class="groovyTestCase">assert [1,2,3] == [1,2,3].iterator().collect()</pre>
+     *
+     * @param self an aggregate Object with an Iterator returning its items
+     * @return a Collection of the transformed values
+     * @see Closure#IDENTITY
+     * @since 1.8.5
+     */
+    public static Collection collect(Object self) {
+        return collect(self, Closure.IDENTITY);
+    }
+
+    /**
      * Iterates through this aggregate Object transforming each item into a new value using the
      * <code>transform</code> closure, returning a list of transformed values.
      * Example:
@@ -3371,62 +3396,163 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
     }
 
     /**
-     * Iterates through this aggregate Object transforming each item into a new value using Closure.IDENTITY
-     * as a transformer, basically returning a list of items copied from the original object.
-     * <pre class="groovyTestCase">assert [1,2,3] == [1,2,3].iterator().collect()</pre>
+     * Iterates through this aggregate Object transforming each item into a new value using the <code>transform</code> closure
+     * and adding it to the supplied <code>collector</code>.
      *
-     * @param self an aggregate Object with an Iterator returning its items
+     * @param self      an aggregate Object with an Iterator returning its items
+     * @param collector the Collection to which the transformed values are added
+     * @param transform the closure used to transform each item of the aggregate object
+     * @return the collector with all transformed values added to it
+     * @since 1.0
+     */
+    public static <T> Collection<T> collect(Object self, Collection<T> collector, Closure<? extends T> transform) {
+        return collect(InvokerHelper.asIterator(self), collector, transform);
+    }
+
+    /**
+     * Iterates through this Array transforming each item into a new value using the
+     * <code>transform</code> closure, returning a list of transformed values.
+     *
+     * @param self      an Array
+     * @param transform the closure used to transform each item of the Array
      * @return a List of the transformed values
-     * @see Closure#IDENTITY
-     * @since 1.8.5
+     * @since 2.5.0
      */
-    public static Collection collect(Object self) {
-        return collect(self, Closure.IDENTITY);
+    public static <S,T> List<T> collect(S[] self, @ClosureParams(FirstParam.Component.class) Closure<T> transform) {
+        return collect(new ArrayIterator<S>(self), transform);
     }
 
     /**
-     * Iterates through this aggregate Object transforming each item into a new value using the <code>transform</code> closure
+     * Iterates through this Array transforming each item into a new value using the <code>transform</code> closure
      * and adding it to the supplied <code>collector</code>.
+     * <pre class="groovyTestCase">
+     * Integer[] nums = [1,2,3]
+     * List<Integer> answer = []
+     * nums.collect(answer) { it * 2 }
+     * assert [2,4,6] == answer
+     * </pre>
      *
-     * @param self      an aggregate Object with an Iterator returning its items
+     * @param self      an Array
      * @param collector the Collection to which the transformed values are added
-     * @param transform the closure used to transform each item of the aggregate object
+     * @param transform the closure used to transform each item
      * @return the collector with all transformed values added to it
-     * @since 1.0
+     * @since 2.5.0
      */
-    public static <T> Collection<T> collect(Object self, Collection<T> collector, Closure<? extends T> transform) {
-        for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext(); ) {
-            collector.add(transform.call(iter.next()));
+    public static <S,T> Collection<T> collect(S[] self, Collection<T> collector, @ClosureParams(FirstParam.Component.class) Closure<? extends T> transform) {
+        return collect(new ArrayIterator<S>(self), collector, transform);
+    }
+
+    /**
+     * Iterates through this Iterator transforming each item into a new value using the
+     * <code>transform</code> closure, returning a list of transformed values.
+     *
+     * @param self      an Iterator
+     * @param transform the closure used to transform each item
+     * @return a List of the transformed values
+     * @since 2.5.0
+     */
+    public static <S,T> List<T> collect(Iterator<S> self, @ClosureParams(FirstParam.Component.class) Closure<T> transform) {
+        return (List<T>) collect(self, new ArrayList<T>(), transform);
+    }
+
+    /**
+     * Iterates through this Iterator transforming each item into a new value using the <code>transform</code> closure
+     * and adding it to the supplied <code>collector</code>.
+     *
+     * @param self      an Iterator
+     * @param collector the Collection to which the transformed values are added
+     * @param transform the closure used to transform each item
+     * @return the collector with all transformed values added to it
+     * @since 2.5.0
+     */
+    public static <S,T> Collection<T> collect(Iterator<S> self, Collection<T> collector, @ClosureParams(FirstParam.FirstGenericType.class) Closure<? extends T> transform) {
+        while (self.hasNext()) {
+            collector.add(transform.call(self.next()));
         }
         return collector;
     }
 
     /**
+     * Iterates through this collection transforming each entry into a new value using Closure.IDENTITY
+     * as a transformer, basically returning a list of items copied from the original collection.
+     * <pre class="groovyTestCase">assert [1,2,3] == [1,2,3].collect()</pre>
+     *
+     * @param self a collection
+     * @return a List of the transformed values
+     * @see Closure#IDENTITY
+     * @since 1.8.5
+     * @deprecated use the Iterable version instead
+     */
+    @Deprecated
+    public static <T> List<T> collect(Collection<T> self) {
+        return collect((Iterable<T>) self);
+    }
+
+    /**
      * Iterates through this collection transforming each entry into a new value using the <code>transform</code> closure
      * returning a list of transformed values.
-     * <pre class="groovyTestCase">assert [2,4,6] == [1,2,3].collect { it * 2 }</pre>
      *
      * @param self      a collection
      * @param transform the closure used to transform each item of the collection
      * @return a List of the transformed values
+     * @deprecated use the Iterable version instead
      * @since 1.0
      */
+    @Deprecated
     public static <S,T> List<T> collect(Collection<S> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> transform) {
         return (List<T>) collect(self, new ArrayList<T>(self.size()), transform);
     }
 
     /**
+     * Iterates through this collection transforming each value into a new value using the <code>transform</code> closure
+     * and adding it to the supplied <code>collector</code>.
+     * <pre class="groovyTestCase">assert [1,2,3] as HashSet == [2,4,5,6].collect(new HashSet()) { (int)(it / 2) }</pre>
+     *
+     * @param self      a collection
+     * @param collector the Collection to which the transformed values are added
+     * @param transform the closure used to transform each item of the collection
+     * @return the collector with all transformed values added to it
+     * @deprecated use the Iterable version instead
+     * @since 1.0
+     */
+    @Deprecated
+    public static <S,T> Collection<T> collect(Collection<S> self, Collection<T> collector, @ClosureParams(FirstParam.FirstGenericType.class) Closure<? extends T> transform) {
+        for (S item : self) {
+            collector.add(transform.call(item));
+            if (transform.getDirective() == Closure.DONE) {
+                break;
+            }
+        }
+        return collector;
+    }
+
+    /**
      * Iterates through this collection transforming each entry into a new value using Closure.IDENTITY
      * as a transformer, basically returning a list of items copied from the original collection.
      * <pre class="groovyTestCase">assert [1,2,3] == [1,2,3].collect()</pre>
      *
-     * @param self    a collection
+     * @param self an Iterable
      * @return a List of the transformed values
-     * @since 1.8.5
      * @see Closure#IDENTITY
+     * @since 2.5.0
      */
-    public static <T> List<T> collect(Collection<T> self) {
-        return (List<T>) collect(self, Closure.IDENTITY);
+    @SuppressWarnings("unchecked")
+    public static <T> List<T> collect(Iterable<T> self) {
+        return collect(self, (Closure<T>) Closure.IDENTITY);
+    }
+
+    /**
+     * Iterates through this Iterable transforming each entry into a new value using the <code>transform</code> closure
+     * returning a list of transformed values.
+     * <pre class="groovyTestCase">assert [2,4,6] == [1,2,3].collect { it * 2 }</pre>
+     *
+     * @param self      an Iterable
+     * @param transform the closure used to transform each item of the collection
+     * @return a List of the transformed values
+     * @since 2.5.0
+     */
+    public static <S,T> List<T> collect(Iterable<S> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> transform) {
+        return (List<T>) collect(self.iterator(), transform);
     }
 
     /**
@@ -3434,14 +3560,14 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * and adding it to the supplied <code>collector</code>.
      * <pre class="groovyTestCase">assert [1,2,3] as HashSet == [2,4,5,6].collect(new HashSet()) { (int)(it / 2) }</pre>
      *
-     * @param self      a collection
+     * @param self      an Iterable
      * @param collector the Collection to which the transformed values are added
-     * @param transform the closure used to transform each item of the collection
+     * @param transform the closure used to transform each item
      * @return the collector with all transformed values added to it
-     * @since 1.0
+     * @since 2.5.0
      */
-    public static <T,E> Collection<T> collect(Collection<E> self, Collection<T> collector, @ClosureParams(FirstParam.FirstGenericType.class) Closure<? extends T> transform) {
-        for (E item : self) {
+    public static <S,T> Collection<T> collect(Iterable<S> self, Collection<T> collector, @ClosureParams(FirstParam.FirstGenericType.class) Closure<? extends T> transform) {
+        for (S item : self) {
             collector.add(transform.call(item));
             if (transform.getDirective() == Closure.DONE) {
                 break;
@@ -4121,52 +4247,6 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
     }
 
     /**
-     * Treats the object as iterable, iterating through the values it represents and returns the first non-null result obtained from calling the closure, otherwise returns the defaultResult.
-     *
-     * <pre class="groovyTestCase">
-     * int[] numbers = [1, 2, 3]
-     * assert numbers.findResult(5) { if(it > 1) return it } == 2
-     * assert numbers.findResult(5) { if(it > 4) return it } == 5
-     * </pre>
-     *
-     * @param self    an Object with an iterator returning its values
-     * @param defaultResult an Object that should be returned if all closure results are null
-     * @param closure a closure that returns a non-null value when processing should stop
-     * @return the first non-null result of the closure, otherwise the default value
-     * @since 1.7.5
-     */
-    public static Object findResult(Object self, Object defaultResult, Closure closure) {
-        Object result = findResult(self, closure);
-        if (result == null) return defaultResult;
-        return result;
-    }
-
-    /**
-     * Treats the object as iterable, iterating through the values it represents and returns the first non-null result obtained from calling the closure, otherwise returns null.
-     *
-     * <pre class="groovyTestCase">
-     * int[] numbers = [1, 2, 3]
-     * assert numbers.findResult { if(it > 1) return it } == 2
-     * assert numbers.findResult { if(it > 4) return it } == null
-     * </pre>
-     *
-     * @param self    an Object with an iterator returning its values
-     * @param closure a closure that returns a non-null value when processing should stop
-     * @return the first non-null result of the closure
-     * @since 1.7.5
-     */
-    public static Object findResult(Object self, Closure closure) {
-        for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
-            Object value = iter.next();
-            Object result = closure.call(value);
-            if (result != null) {
-                return result;
-            }
-        }
-        return null;
-    }
-
-    /**
      * Finds the first value matching the closure condition.  Example:
      * <pre class="groovyTestCase">def list = [1,2,3]
      * assert 2 == list.find { it > 1 }
@@ -4230,46 +4310,206 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
     }
 
     /**
+     * Treats the object as iterable, iterating through the values it represents and returns the first non-null result obtained from calling the closure, otherwise returns null.
+     * <p>
+     * <pre class="groovyTestCase">
+     * int[] numbers = [1, 2, 3]
+     * assert numbers.findResult { if(it > 1) return it } == 2
+     * assert numbers.findResult { if(it > 4) return it } == null
+     * </pre>
+     *
+     * @param self      an Object with an iterator returning its values
+     * @param condition a closure that returns a non-null value to indicate that processing should stop and the value should be returned
+     * @return the first non-null result of the closure
+     * @since 1.7.5
+     */
+    public static Object findResult(Object self, Closure condition) {
+        for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext(); ) {
+            Object value = iter.next();
+            Object result = condition.call(value);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Treats the object as iterable, iterating through the values it represents and returns the first non-null result obtained from calling the closure, otherwise returns the defaultResult.
+     * <p>
+     * <pre class="groovyTestCase">
+     * int[] numbers = [1, 2, 3]
+     * assert numbers.findResult(5) { if(it > 1) return it } == 2
+     * assert numbers.findResult(5) { if(it > 4) return it } == 5
+     * </pre>
+     *
+     * @param self          an Object with an iterator returning its values
+     * @param defaultResult an Object that should be returned if all closure results are null
+     * @param condition     a closure that returns a non-null value to indicate that processing should stop and the value should be returned
+     * @return the first non-null result of the closure, otherwise the default value
+     * @since 1.7.5
+     */
+    public static Object findResult(Object self, Object defaultResult, Closure condition) {
+        Object result = findResult(self, condition);
+        if (result == null) return defaultResult;
+        return result;
+    }
+
+    /**
+     * Iterates through the collection calling the given closure for each item but stopping once the first non-null
+     * result is found and returning that result. If all are null, the defaultResult is returned.
+     *
+     * @param self          a Collection
+     * @param defaultResult an Object that should be returned if all closure results are null
+     * @param condition     a closure that returns a non-null value to indicate that processing should stop and the value should be returned
+     * @return the first non-null result from calling the closure, or the defaultValue
+     * @since 1.7.5
+     * @deprecated use the Iterable version instead
+     */
+    @Deprecated
+    public static <S, T, U extends T, V extends T> T findResult(Collection<S> self, U defaultResult, @ClosureParams(FirstParam.FirstGenericType.class) Closure<V> condition) {
+        return findResult((Iterable<S>) self, defaultResult, condition);
+    }
+
+    /**
      * Iterates through the collection calling the given closure for each item but stopping once the first non-null
+     * result is found and returning that result. If all results are null, null is returned.
+     *
+     * @param self      a Collection
+     * @param condition a closure that returns a non-null value to indicate that processing should stop and the value should be returned
+     * @return the first non-null result from calling the closure, or null
+     * @since 1.7.5
+     * @deprecated use the Iterable version instead
+     */
+    @Deprecated
+    public static <S,T> T findResult(Collection<S> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> condition) {
+        return findResult((Iterable<S>) self, condition);
+    }
+
+    /**
+     * Iterates through the Iterator calling the given closure condition for each item but stopping once the first non-null
      * result is found and returning that result. If all are null, the defaultResult is returned.
      * <p>
      * Examples:
      * <pre class="groovyTestCase">
-     * def list = [1,2,3]
-     * assert "Found 2" == list.findResult("default") { it > 1 ? "Found $it" : null }
-     * assert "default" == list.findResult("default") { it > 3 ? "Found $it" : null }
+     * def iter = [1,2,3].iterator()
+     * assert "Found 2" == iter.findResult("default") { it > 1 ? "Found $it" : null }
+     * assert "default" == iter.findResult("default") { it > 3 ? "Found $it" : null }
      * </pre>
      *
-     * @param self          a Collection
+     * @param self          an Iterator
      * @param defaultResult an Object that should be returned if all closure results are null
-     * @param closure a closure that returns a non-null value when processing should stop and a value should be returned
+     * @param condition     a closure that returns a non-null value to indicate that processing should stop and the value should be returned
      * @return the first non-null result from calling the closure, or the defaultValue
-     * @since 1.7.5
+     * @since 2.5.0
      */
-    public static <T, U extends T, V extends T,E> T findResult(Collection<E> self, U defaultResult, @ClosureParams(FirstParam.FirstGenericType.class) Closure<V> closure) {
-        T result = findResult(self, closure);
+    public static <S, T, U extends T, V extends T> T findResult(Iterator<S> self, U defaultResult, @ClosureParams(FirstParam.FirstGenericType.class) Closure<V> condition) {
+        T result = findResult(self, condition);
         if (result == null) return defaultResult;
         return result;
     }
 
     /**
-     * Iterates through the collection calling the given closure for each item but stopping once the first non-null
+     * Iterates through the Iterator calling the given closure condition for each item but stopping once the first non-null
      * result is found and returning that result. If all results are null, null is returned.
+     *
+     * @param self      an Iterator
+     * @param condition a closure that returns a non-null value to indicate that processing should stop and the value should be returned
+     * @return the first non-null result from calling the closure, or null
+     * @since 2.5.0
+     */
+    public static <T, U> T findResult(Iterator<U> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> condition) {
+        while (self.hasNext()) {
+            U next = self.next();
+            T result = condition.call(next);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Iterates through the Iterable calling the given closure condition for each item but stopping once the first non-null
+     * result is found and returning that result. If all are null, the defaultResult is returned.
      * <p>
-     * Example:
+     * Examples:
      * <pre class="groovyTestCase">
      * def list = [1,2,3]
-     * assert "Found 2" == list.findResult { it > 1 ? "Found $it" : null }
+     * assert "Found 2" == list.findResult("default") { it > 1 ? "Found $it" : null }
+     * assert "default" == list.findResult("default") { it > 3 ? "Found $it" : null }
      * </pre>
      *
-     * @param self    a Collection
-     * @param closure a closure that returns a non-null value when processing should stop and a value should be returned
+     * @param self          an Iterable
+     * @param defaultResult an Object that should be returned if all closure results are null
+     * @param condition     a closure that returns a non-null value to indicate that processing should stop and the value should be returned
+     * @return the first non-null result from calling the closure, or the defaultValue
+     * @since 2.5.0
+     */
+    public static <S, T, U extends T, V extends T> T findResult(Iterable<S> self, U defaultResult, @ClosureParams(FirstParam.FirstGenericType.class) Closure<V> condition) {
+        T result = findResult(self, condition);
+        if (result == null) return defaultResult;
+        return result;
+    }
+
+    /**
+     * Iterates through the Iterable calling the given closure condition for each item but stopping once the first non-null
+     * result is found and returning that result. If all results are null, null is returned.
+     *
+     * @param self      an Iterable
+     * @param condition a closure that returns a non-null value to indicate that processing should stop and the value should be returned
+     * @return the first non-null result from calling the closure, or null
+     * @since 2.5.0
+     */
+    public static <T, U> T findResult(Iterable<U> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> condition) {
+        return findResult(self.iterator(), condition);
+    }
+
+    /**
+     * Iterates through the Array calling the given closure condition for each item but stopping once the first non-null
+     * result is found and returning that result. If all are null, the defaultResult is returned.
+     *
+     * @param self          an Array
+     * @param defaultResult an Object that should be returned if all closure results are null
+     * @param condition     a closure that returns a non-null value to indicate that processing should stop and the value should be returned
+     * @return the first non-null result from calling the closure, or the defaultValue
+     * @since 2.5.0
+     */
+    public static <S, T, U extends T, V extends T> T findResult(S[] self, U defaultResult, @ClosureParams(FirstParam.Component.class) Closure<V> condition) {
+        return findResult(new ArrayIterator<S>(self), defaultResult, condition);
+    }
+
+    /**
+     * Iterates through the Array calling the given closure condition for each item but stopping once the first non-null
+     * result is found and returning that result. If all results are null, null is returned.
+     *
+     * @param self      an Array
+     * @param condition a closure that returns a non-null value to indicate that processing should stop and the value should be returned
      * @return the first non-null result from calling the closure, or null
+     * @since 2.5.0
+     */
+    public static <S, T> T findResult(S[] self, @ClosureParams(FirstParam.Component.class) Closure<T> condition) {
+        return findResult(new ArrayIterator<S>(self), condition);
+    }
+
+    /**
+     * Returns the first non-null closure result found by passing each map entry to the closure, otherwise null is returned.
+     * If the closure takes two parameters, the entry key and value are passed.
+     * If the closure takes one parameter, the Map.Entry object is passed.
+     * <pre class="groovyTestCase">
+     * assert "Found b:3" == [a:1, b:3].findResult { if (it.value == 3) return "Found ${it.key}:${it.value}" }
+     * assert null == [a:1, b:3].findResult { if (it.value == 9) return "Found ${it.key}:${it.value}" }
+     * assert "Found a:1" == [a:1, b:3].findResult { k, v -> if (k.size() + v == 2) return "Found $k:$v" }
+     * </pre>
+     *
+     * @param self      a Map
+     * @param condition a 1 or 2 arg Closure that returns a non-null value when processing should stop and a value should be returned
+     * @return the first non-null result collected by calling the closure, or null if no such result was found
      * @since 1.7.5
      */
-    public static <T,U> T findResult(Collection<U> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> closure) {
-        for (Object value : self) {
-            T result = closure.call(value);
+    public static <T, K, V> T findResult(Map<K, V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure<T> condition) {
+        for (Map.Entry<K, V> entry : self.entrySet()) {
+            T result = callClosureForMapEntry(condition, entry);
             if (result != null) {
                 return result;
             }
@@ -4278,13 +4518,35 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
     }
 
     /**
-     * @deprecated Use the Iterable version of findResults instead
+     * Returns the first non-null closure result found by passing each map entry to the closure, otherwise the defaultResult is returned.
+     * If the closure takes two parameters, the entry key and value are passed.
+     * If the closure takes one parameter, the Map.Entry object is passed.
+     * <pre class="groovyTestCase">
+     * assert "Found b:3" == [a:1, b:3].findResult("default") { if (it.value == 3) return "Found ${it.key}:${it.value}" }
+     * assert "default" == [a:1, b:3].findResult("default") { if (it.value == 9) return "Found ${it.key}:${it.value}" }
+     * assert "Found a:1" == [a:1, b:3].findResult("default") { k, v -> if (k.size() + v == 2) return "Found $k:$v" }
+     * </pre>
+     *
+     * @param self          a Map
+     * @param defaultResult an Object that should be returned if all closure results are null
+     * @param condition     a 1 or 2 arg Closure that returns a non-null value when processing should stop and a value should be returned
+     * @return the first non-null result collected by calling the closure, or the defaultResult if no such result was found
+     * @since 1.7.5
+     */
+    public static <T, U extends T, V extends T, A, B> T findResult(Map<A, B> self, U defaultResult, @ClosureParams(MapEntryOrKeyValue.class) Closure<V> condition) {
+        T result = findResult(self, condition);
+        if (result == null) return defaultResult;
+        return result;
+    }
+
+    /**
      * @see #findResults(Iterable, Closure)
      * @since 1.8.1
+     * @deprecated Use the Iterable version of findResults instead
      */
     @Deprecated
-    public static <T,U> Collection<T> findResults(Collection<U> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> filteringTransform) {
-        return findResults((Iterable<?>)self, filteringTransform);
+    public static <T, U> Collection<T> findResults(Collection<U> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> filteringTransform) {
+        return findResults((Iterable<?>) self, filteringTransform);
     }
 
     /**
@@ -4298,14 +4560,28 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * assert result == ["Found 2", "Found 3"]
      * </pre>
      *
-     * @param self               an Iterable
+     * @param self               an Iterable
+     * @param filteringTransform a Closure that should return either a non-null transformed value or null for items which should be discarded
+     * @return the list of non-null transformed values
+     * @since 2.2.0
+     */
+    public static <T, U> Collection<T> findResults(Iterable<U> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> filteringTransform) {
+        return findResults(self.iterator(), filteringTransform);
+    }
+
+    /**
+     * Iterates through the Iterator transforming items using the supplied closure
+     * and collecting any non-null results.
+     *
+     * @param self               an Iterator
      * @param filteringTransform a Closure that should return either a non-null transformed value or null for items which should be discarded
      * @return the list of non-null transformed values
-     * @since 2.2.0
+     * @since 2.5.0
      */
-    public static <T,U> Collection<T> findResults(Iterable<U> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> filteringTransform) {
+    public static <T, U> Collection<T> findResults(Iterator<U> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<T> filteringTransform) {
         List<T> result = new ArrayList<T>();
-        for (Object value : self) {
+        while (self.hasNext()) {
+            U value = self.next();
             T transformed = filteringTransform.call(value);
             if (transformed != null) {
                 result.add(transformed);
@@ -4315,6 +4591,19 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
     }
 
     /**
+     * Iterates through the Array transforming items using the supplied closure
+     * and collecting any non-null results.
+     *
+     * @param self               an Array
+     * @param filteringTransform a Closure that should return either a non-null transformed value or null for items which should be discarded
+     * @return the list of non-null transformed values
+     * @since 2.5.0
+     */
+    public static <T, U> Collection<T> findResults(U[] self, @ClosureParams(FirstParam.Component.class) Closure<T> filteringTransform) {
+        return findResults(new ArrayIterator<U>(self), filteringTransform);
+    }
+
+    /**
      * Iterates through the map transforming items using the supplied closure
      * and collecting any non-null results.
      * If the closure takes two parameters, the entry key and value are passed.
@@ -4332,7 +4621,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * @return the list of non-null transformed values
      * @since 1.8.1
      */
-    public static <T,K,V> Collection<T> findResults(Map<K, V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure<T> filteringTransform) {
+    public static <T, K, V> Collection<T> findResults(Map<K, V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure<T> filteringTransform) {
         List<T> result = new ArrayList<T>();
         for (Map.Entry<K, V> entry : self.entrySet()) {
             T transformed = callClosureForMapEntry(filteringTransform, entry);
@@ -4365,53 +4654,6 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
     }
 
     /**
-     * Returns the first non-null closure result found by passing each map entry to the closure, otherwise the defaultResult is returned.
-     * If the closure takes two parameters, the entry key and value are passed.
-     * If the closure takes one parameter, the Map.Entry object is passed.
-     * <pre class="groovyTestCase">
-     * assert "Found b:3" == [a:1, b:3].findResult("default") { if (it.value == 3) return "Found ${it.key}:${it.value}" }
-     * assert "default" == [a:1, b:3].findResult("default") { if (it.value == 9) return "Found ${it.key}:${it.value}" }
-     * assert "Found a:1" == [a:1, b:3].findResult("default") { k, v -> if (k.size() + v == 2) return "Found $k:$v" }
-     * </pre>
-     *
-     * @param self    a Map
-     * @param defaultResult an Object that should be returned if all closure results are null
-     * @param closure a 1 or 2 arg Closure that returns a non-null value when processing should stop and a value should be returned
-     * @return the first non-null result collected by calling the closure, or the defaultResult if no such result was found
-     * @since 1.7.5
-     */
-    public static <T, U extends T, V extends T,A,B> T findResult(Map<A, B> self, U defaultResult, @ClosureParams(MapEntryOrKeyValue.class) Closure<V> closure) {
-        T result = findResult(self, closure);
-        if (result == null) return defaultResult;
-        return result;
-    }
-
-    /**
-     * Returns the first non-null closure result found by passing each map entry to the closure, otherwise null is returned.
-     * If the closure takes two parameters, the entry key and value are passed.
-     * If the closure takes one parameter, the Map.Entry object is passed.
-     * <pre class="groovyTestCase">
-     * assert "Found b:3" == [a:1, b:3].findResult { if (it.value == 3) return "Found ${it.key}:${it.value}" }
-     * assert null == [a:1, b:3].findResult { if (it.value == 9) return "Found ${it.key}:${it.value}" }
-     * assert "Found a:1" == [a:1, b:3].findResult { k, v -> if (k.size() + v == 2) return "Found $k:$v" }
-     * </pre>
-     *
-     * @param self    a Map
-     * @param closure a 1 or 2 arg Closure that returns a non-null value when processing should stop and a value should be returned
-     * @return the first non-null result collected by calling the closure, or null if no such result was found
-     * @since 1.7.5
-     */
-    public static <T,K,V> T findResult(Map<K, V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure<T> closure) {
-        for (Map.Entry<K, V> entry : self.entrySet()) {
-            T result = callClosureForMapEntry(closure, entry);
-            if (result != null) {
-                return result;
-            }
-        }
-        return null;
-    }
-
-    /**
      * Finds all values matching the closure condition.
      * <pre class="groovyTestCase">assert ([2,4] as Set) == ([1,2,3,4] as Set).findAll { it % 2 == 0 }</pre>
      *
@@ -4872,6 +5114,23 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return split(closure, accept, reject, iter);
     }
 
+    /**
+     * Splits all items into two collections based on the closure condition.
+     * The first list contains all items which match the closure expression.
+     * The second list all those that don't.
+     *
+     * @param self    an Array
+     * @param closure a closure condition
+     * @return a List whose first item is the accepted values and whose second item is the rejected values
+     * @since 2.5.0
+     */
+    public static <T> Collection<Collection<T>> split(T[] self, @ClosureParams(FirstParam.Component.class) Closure closure) {
+        List<T> accept = new ArrayList<T>();
+        List<T> reject = new ArrayList<T>();
+        Iterator<T> iter = new ArrayIterator<T>(self);
+        return split(closure, accept, reject, iter);
+    }
+
     private static <T> Collection<Collection<T>> split(Closure closure, Collection<T> accept, Collection<T> reject, Iterator<T> iter) {
         List<Collection<T>> answer = new ArrayList<Collection<T>>();
         BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
@@ -6181,8 +6440,8 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      *         item of the Iterable.
      * @since 2.2.0
      */
-    public static Object sum(Iterable self, Closure closure) {
-        return sum(self, null, closure, true);
+    public static <T> Object sum(Iterable<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
+        return sum(self.iterator(), null, closure, true);
     }
 
     /**
@@ -6196,8 +6455,8 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      *         item of the array.
      * @since 1.7.1
      */
-    public static Object sum(Object[] self, Closure closure) {
-        return sum(toList(self), null, closure, true);
+    public static <T> Object sum(T[] self, @ClosureParams(FirstParam.Component.class) Closure closure) {
+        return sum(new ArrayIterator<T>(self), null, closure, true);
     }
 
     /**
@@ -6212,8 +6471,8 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      *         item from the Iterator.
      * @since 1.7.1
      */
-    public static Object sum(Iterator<Object> self, Closure closure) {
-        return sum(toList(self), null, closure, true);
+    public static <T> Object sum(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
+        return sum(self, null, closure, true);
     }
 
     /**
@@ -6239,8 +6498,8 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      *         item of the collection.
      * @since 1.5.0
      */
-    public static Object sum(Iterable self, Object initialValue, Closure closure) {
-        return sum(self, initialValue, closure, false);
+    public static <T> Object sum(Iterable<T> self, Object initialValue, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
+        return sum(self.iterator(), initialValue, closure, false);
     }
 
     /**
@@ -6255,8 +6514,8 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      *         item of the array.
      * @since 1.7.1
      */
-    public static Object sum(Object[] self, Object initialValue, Closure closure) {
-        return sum(toList(self), initialValue, closure, false);
+    public static <T> Object sum(T[] self, Object initialValue, @ClosureParams(FirstParam.Component.class) Closure closure) {
+        return sum(new ArrayIterator<T>(self), initialValue, closure, false);
     }
 
     /**
@@ -6272,16 +6531,16 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      *         item from the Iterator.
      * @since 1.7.1
      */
-    public static Object sum(Iterator<Object> self, Object initialValue, Closure closure) {
-        return sum(toList(self), initialValue, closure, false);
+    public static <T> Object sum(Iterator<T> self, Object initialValue, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
+        return sum(self, initialValue, closure, false);
     }
 
-    private static Object sum(Iterable self, Object initialValue, Closure closure, boolean first) {
+    private static <T> Object sum(Iterator<T> self, Object initialValue, Closure closure, boolean first) {
         Object result = initialValue;
         Object[] closureParam = new Object[1];
         Object[] plusParam = new Object[1];
-        for (Object next : self) {
-            closureParam[0] = next;
+        while (self.hasNext()) {
+            closureParam[0] = self.next();
             plusParam[0] = closure.call(closureParam);
             if (first) {
                 result = plusParam[0];
@@ -16047,40 +16306,68 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
     }
 
     /**
-     * Iterates over the elements of an iterable collection of items and returns
+     * Iterates over the elements of an aggregate of items and returns
      * the index of the first item that matches the condition specified in the closure.
      *
-     * @param self    the iteration object over which to iterate
-     * @param closure the filter to perform a match on the collection
+     * @param self      the iteration object over which to iterate
+     * @param condition the matching condition
      * @return an integer that is the index of the first matched object or -1 if no match was found
      * @since 1.0
      */
-    public static int findIndexOf(Object self, Closure closure) {
-        return findIndexOf(self, 0, closure);
+    public static int findIndexOf(Object self, Closure condition) {
+        return findIndexOf(self, 0, condition);
     }
 
     /**
-     * Iterates over the elements of an iterable collection of items, starting from a
+     * Iterates over the elements of an aggregate of items, starting from a
      * specified startIndex, and returns the index of the first item that matches the
      * condition specified in the closure.
      *
      * @param self       the iteration object over which to iterate
      * @param startIndex start matching from this index
-     * @param closure    the filter to perform a match on the collection
+     * @param condition  the matching condition
      * @return an integer that is the index of the first matched object or -1 if no match was found
      * @since 1.5.0
      */
-    public static int findIndexOf(Object self, int startIndex, Closure closure) {
+    public static int findIndexOf(Object self, int startIndex, Closure condition) {
+        return findIndexOf(InvokerHelper.asIterator(self), condition);
+    }
+
+    /**
+     * Iterates over the elements of an Iterator and returns the index of the first item that satisfies the
+     * condition specified by the closure.
+     *
+     * @param self      an Iterator
+     * @param condition the matching condition
+     * @return an integer that is the index of the first matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findIndexOf(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
+        return findIndexOf(self, 0, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Iterator, starting from a
+     * specified startIndex, and returns the index of the first item that satisfies the
+     * condition specified by the closure.
+     *
+     * @param self       an Iterator
+     * @param startIndex start matching from this index
+     * @param condition  the matching condition
+     * @return an integer that is the index of the first matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findIndexOf(Iterator<T> self, int startIndex, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
         int result = -1;
         int i = 0;
-        BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
-        for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext(); i++) {
-            Object value = iter.next();
-            if (i < startIndex) {
+        BooleanClosureWrapper bcw = new BooleanClosureWrapper(condition);
+        while (self.hasNext()) {
+            Object value = self.next();
+            if (i++ < startIndex) {
                 continue;
             }
             if (bcw.call(value)) {
-                result = i;
+                result = i - 1;
                 break;
             }
         }
@@ -16088,87 +16375,312 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
     }
 
     /**
-     * Iterates over the elements of an iterable collection of items and returns
+     * Iterates over the elements of an Iterable and returns the index of the first item that satisfies the
+     * condition specified by the closure.
+     *
+     * @param self      an Iterable
+     * @param condition the matching condition
+     * @return an integer that is the index of the first matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findIndexOf(Iterable<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
+        return findIndexOf(self, 0, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Iterable, starting from a
+     * specified startIndex, and returns the index of the first item that satisfies the
+     * condition specified by the closure.
+     *
+     * @param self       an Iterable
+     * @param startIndex start matching from this index
+     * @param condition  the matching condition
+     * @return an integer that is the index of the first matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findIndexOf(Iterable<T> self, int startIndex, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
+        return findIndexOf(self.iterator(), startIndex, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Array and returns the index of the first item that satisfies the
+     * condition specified by the closure.
+     *
+     * @param self      an Array
+     * @param condition the matching condition
+     * @return an integer that is the index of the first matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findIndexOf(T[] self, @ClosureParams(FirstParam.Component.class) Closure condition) {
+        return findIndexOf(self, 0, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Array, starting from a
+     * specified startIndex, and returns the index of the first item that satisfies the
+     * condition specified by the closure.
+     *
+     * @param self       an Array
+     * @param startIndex start matching from this index
+     * @param condition  the matching condition
+     * @return an integer that is the index of the first matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findIndexOf(T[] self, int startIndex, @ClosureParams(FirstParam.Component.class) Closure condition) {
+        return findIndexOf(new ArrayIterator<T>(self), startIndex, condition);
+    }
+
+    /**
+     * Iterates over the elements of an aggregate of items and returns
      * the index of the last item that matches the condition specified in the closure.
      *
-     * @param self    the iteration object over which to iterate
-     * @param closure the filter to perform a match on the collection
+     * @param self      the iteration object over which to iterate
+     * @param condition the matching condition
      * @return an integer that is the index of the last matched object or -1 if no match was found
      * @since 1.5.2
      */
-    public static int findLastIndexOf(Object self, Closure closure) {
-        return findLastIndexOf(self, 0, closure);
+    public static int findLastIndexOf(Object self, Closure condition) {
+        return findLastIndexOf(self, 0, condition);
     }
 
     /**
-     * Iterates over the elements of an iterable collection of items, starting
+     * Iterates over the elements of an aggregate of items, starting
      * from a specified startIndex, and returns the index of the last item that
      * matches the condition specified in the closure.
      *
      * @param self       the iteration object over which to iterate
      * @param startIndex start matching from this index
-     * @param closure    the filter to perform a match on the collection
+     * @param condition  the matching condition
      * @return an integer that is the index of the last matched object or -1 if no match was found
      * @since 1.5.2
      */
-    public static int findLastIndexOf(Object self, int startIndex, Closure closure) {
+    public static int findLastIndexOf(Object self, int startIndex, Closure condition) {
+        return findLastIndexOf(InvokerHelper.asIterator(self), startIndex, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Iterator and returns
+     * the index of the last item that matches the condition specified in the closure.
+     *
+     * @param self      an Iterator
+     * @param condition the matching condition
+     * @return an integer that is the index of the last matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findLastIndexOf(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
+        return findLastIndexOf(self, 0, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Iterator, starting
+     * from a specified startIndex, and returns the index of the last item that
+     * matches the condition specified in the closure.
+     *
+     * @param self       an Iterator
+     * @param startIndex start matching from this index
+     * @param condition  the matching condition
+     * @return an integer that is the index of the last matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findLastIndexOf(Iterator<T> self, int startIndex, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
         int result = -1;
         int i = 0;
-        BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
-        for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext(); i++) {
-            Object value = iter.next();
-            if (i < startIndex) {
+        BooleanClosureWrapper bcw = new BooleanClosureWrapper(condition);
+        while (self.hasNext()) {
+            Object value = self.next();
+            if (i++ < startIndex) {
                 continue;
             }
             if (bcw.call(value)) {
-                result = i;
+                result = i - 1;
             }
         }
         return result;
     }
 
     /**
-     * Iterates over the elements of an iterable collection of items and returns
+     * Iterates over the elements of an Iterable and returns
+     * the index of the last item that matches the condition specified in the closure.
+     *
+     * @param self      an Iterable
+     * @param condition the matching condition
+     * @return an integer that is the index of the last matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findLastIndexOf(Iterable<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
+        return findLastIndexOf(self.iterator(), 0, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Iterable, starting
+     * from a specified startIndex, and returns the index of the last item that
+     * matches the condition specified in the closure.
+     *
+     * @param self       an Iterable
+     * @param startIndex start matching from this index
+     * @param condition  the matching condition
+     * @return an integer that is the index of the last matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findLastIndexOf(Iterable<T> self, int startIndex, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
+        return findLastIndexOf(self.iterator(), startIndex, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Array and returns
+     * the index of the last item that matches the condition specified in the closure.
+     *
+     * @param self      an Array
+     * @param condition the matching condition
+     * @return an integer that is the index of the last matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findLastIndexOf(T[] self, @ClosureParams(FirstParam.Component.class) Closure condition) {
+        return findLastIndexOf(new ArrayIterator<T>(self), 0, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Array, starting
+     * from a specified startIndex, and returns the index of the last item that
+     * matches the condition specified in the closure.
+     *
+     * @param self       an Array
+     * @param startIndex start matching from this index
+     * @param condition  the matching condition
+     * @return an integer that is the index of the last matched object or -1 if no match was found
+     * @since 2.5.0
+     */
+    public static <T> int findLastIndexOf(T[] self, int startIndex, @ClosureParams(FirstParam.Component.class) Closure condition) {
+        // TODO could be made more efficient by using a reverse index
+        return findLastIndexOf(new ArrayIterator<T>(self), startIndex, condition);
+    }
+
+    /**
+     * Iterates over the elements of an aggregate of items and returns
      * the index values of the items that match the condition specified in the closure.
      *
-     * @param self    the iteration object over which to iterate
-     * @param closure the filter to perform a match on the collection
+     * @param self      the iteration object over which to iterate
+     * @param condition the matching condition
      * @return a list of numbers corresponding to the index values of all matched objects
      * @since 1.5.2
      */
-    public static List<Number> findIndexValues(Object self, Closure closure) {
-        return findIndexValues(self, 0, closure);
+    public static List<Number> findIndexValues(Object self, Closure condition) {
+        return findIndexValues(self, 0, condition);
     }
 
     /**
-     * Iterates over the elements of an iterable collection of items, starting from
+     * Iterates over the elements of an aggregate of items, starting from
      * a specified startIndex, and returns the index values of the items that match
      * the condition specified in the closure.
      *
      * @param self       the iteration object over which to iterate
      * @param startIndex start matching from this index
-     * @param closure    the filter to perform a match on the collection
+     * @param condition  the matching condition
      * @return a list of numbers corresponding to the index values of all matched objects
      * @since 1.5.2
      */
-    public static List<Number> findIndexValues(Object self, Number startIndex, Closure closure) {
+    public static List<Number> findIndexValues(Object self, Number startIndex, Closure condition) {
+        return findIndexValues(InvokerHelper.asIterator(self), startIndex, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Iterator and returns
+     * the index values of the items that match the condition specified in the closure.
+     *
+     * @param self      an Iterator
+     * @param condition the matching condition
+     * @return a list of numbers corresponding to the index values of all matched objects
+     * @since 2.5.0
+     */
+    public static <T> List<Number> findIndexValues(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
+        return findIndexValues(self, 0, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Iterator, starting from
+     * a specified startIndex, and returns the index values of the items that match
+     * the condition specified in the closure.
+     *
+     * @param self       an Iterator
+     * @param startIndex start matching from this index
+     * @param condition  the matching condition
+     * @return a list of numbers corresponding to the index values of all matched objects
+     * @since 2.5.0
+     */
+    public static <T> List<Number> findIndexValues(Iterator<T> self, Number startIndex, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
         List<Number> result = new ArrayList<Number>();
         long count = 0;
         long startCount = startIndex.longValue();
-        BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
-        for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext(); count++) {
-            Object value = iter.next();
-            if (count < startCount) {
+        BooleanClosureWrapper bcw = new BooleanClosureWrapper(condition);
+        while (self.hasNext()) {
+            Object value = self.next();
+            if (count++ < startCount) {
                 continue;
             }
             if (bcw.call(value)) {
-                result.add(count);
+                result.add(count - 1);
             }
         }
         return result;
     }
 
     /**
+     * Iterates over the elements of an Iterable and returns
+     * the index values of the items that match the condition specified in the closure.
+     *
+     * @param self      an Iterable
+     * @param condition the matching condition
+     * @return a list of numbers corresponding to the index values of all matched objects
+     * @since 2.5.0
+     */
+    public static <T> List<Number> findIndexValues(Iterable<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
+        return findIndexValues(self, 0, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Iterable, starting from
+     * a specified startIndex, and returns the index values of the items that match
+     * the condition specified in the closure.
+     *
+     * @param self       an Iterable
+     * @param startIndex start matching from this index
+     * @param condition  the matching condition
+     * @return a list of numbers corresponding to the index values of all matched objects
+     * @since 2.5.0
+     */
+    public static <T> List<Number> findIndexValues(Iterable<T> self, Number startIndex, @ClosureParams(FirstParam.FirstGenericType.class) Closure condition) {
+        return findIndexValues(self.iterator(), startIndex, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Array and returns
+     * the index values of the items that match the condition specified in the closure.
+     *
+     * @param self      an Array
+     * @param condition the matching condition
+     * @return a list of numbers corresponding to the index values of all matched objects
+     * @since 2.5.0
+     */
+    public static <T> List<Number> findIndexValues(T[] self, @ClosureParams(FirstParam.Component.class) Closure condition) {
+        return findIndexValues(self, 0, condition);
+    }
+
+    /**
+     * Iterates over the elements of an Array, starting from
+     * a specified startIndex, and returns the index values of the items that match
+     * the condition specified in the closure.
+     *
+     * @param self       an Array
+     * @param startIndex start matching from this index
+     * @param condition  the matching condition
+     * @return a list of numbers corresponding to the index values of all matched objects
+     * @since 2.5.0
+     */
+    public static <T> List<Number> findIndexValues(T[] self, Number startIndex, @ClosureParams(FirstParam.Component.class) Closure condition) {
+        return findIndexValues(new ArrayIterator<T>(self), startIndex, condition);
+    }
+
+    /**
      * Iterates through the classloader parents until it finds a loader with a class
      * named "org.codehaus.groovy.tools.RootLoader". If there is no such class
      * <code>null</code> will be returned. The name is used for comparison because

http://git-wip-us.apache.org/repos/asf/groovy/blob/047c8f29/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
index cce4682..493802e 100644
--- a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
@@ -18,12 +18,8 @@
  */
 package groovy.transform.stc
 
-import groovy.transform.NotYetImplemented
-
 /**
  * Unit tests for static type checking : closure parameter type inference.
- *
- * @author Cedric Champeau
  */
 class ClosureParamTypeInferenceSTCTest extends StaticTypeCheckingTestCase {
     void testInferenceForDGM_CollectUsingExplicitIt() {
@@ -225,6 +221,16 @@ def items = []
 '''
     }
 
+    void testDGM_collectOnArray() {
+        assertScript '''
+            String[] arr = ['foo', 'bar', 'baz']
+            assert arr.collect { it.startsWith('ba') } == [false, true, true]
+            List<Boolean> answer = [true]
+            arr.collect(answer) { it.startsWith('ba') }
+            assert answer == [true, false, true, true]
+        '''
+    }
+
     void testInferenceOnNonExtensionMethod() {
         assertScript '''import groovy.transform.stc.ClosureParams
             import groovy.transform.stc.FirstParam
@@ -674,6 +680,84 @@ import groovy.transform.stc.ClosureParams
             assert ['foo','bar','baz'].iterator().every { it.length() == 3 }
         '''
     }
+    void testInferenceForDGM_everyOnArray() {
+        assertScript '''
+            String[] items = ['foo','bar','baz']
+            assert items.every { it.length() == 3 }
+            assert items.every { String s -> s.length() == 3 }
+        '''
+    }
+
+    void testInferenceForDGM_findIndexOf() {
+        assertScript '''
+            String[] items1 = ['foo','bar','baz']
+            assert items1.findIndexOf { it.startsWith('ba') == 1 }
+            assert items1.findIndexOf { String s -> s.startsWith('ba') == 1 }
+            def items2 = ['foo','bar','baz']
+            assert items2.findIndexOf { it.startsWith('ba') == 1 }
+            assert items2.iterator().findIndexOf { it.startsWith('ba') == 1 }
+        '''
+    }
+
+    void testInferenceForDGM_findLastIndexOf() {
+        assertScript '''
+            String[] items1 = ['foo','bar','baz']
+            assert items1.findLastIndexOf { it.startsWith('ba') == 2 }
+            assert items1.findLastIndexOf { String s -> s.startsWith('ba') == 2 }
+            def items2 = ['foo','bar','baz']
+            assert items2.findLastIndexOf { it.startsWith('ba') == 2 }
+            assert items2.iterator().findLastIndexOf { it.startsWith('ba') == 2 }
+        '''
+    }
+
+    void testInferenceForDGM_findIndexValues() {
+        assertScript '''
+            String[] items1 = ['foo','bar','baz']
+            assert items1.findIndexValues { it.startsWith('ba') } == [1, 2]
+            assert items1.findIndexValues { String s -> s.startsWith('ba') } == [1, 2]
+            def items2 = ['foo','bar','baz']
+            assert items2.findIndexValues { it.startsWith('ba') } == [1, 2]
+            assert items2.iterator().findIndexValues { it.startsWith('ba') } == [1, 2]
+        '''
+    }
+
+    void testInferenceForDGM_findResult() {
+        assertScript '''
+            String[] items1 = ['foo','bar','baz']
+            assert items1.findResult { it.startsWith('ba') ? it : null } == 'bar'
+            def items2 = ['foo','bar','baz']
+            assert items2.findResult { it.startsWith('ba') ? it : null } == 'bar'
+            assert items2.iterator().findResult { it.startsWith('ba') ? it : null } == 'bar'
+        '''
+    }
+
+    void testInferenceForDGM_findResults() {
+        assertScript '''
+            String[] items1 = ['foo','bar','baz']
+            assert items1.findResults { it.startsWith('ba') ? it : null } == ['bar', 'baz']
+            def items2 = ['foo','bar','baz']
+            assert items2.findResults { it.startsWith('ba') ? it : null } == ['bar', 'baz']
+            assert items2.iterator().findResults { it.startsWith('ba') ? it : null } == ['bar', 'baz']
+        '''
+    }
+
+    void testInferenceForDGM_split() {
+        assertScript '''
+            String[] items1 = ['foo','bar','baz']
+            assert items1.split { it.startsWith('ba') } == [['bar', 'baz'], ['foo']]
+            Collection items2 = ['foo','bar','baz']
+            assert items2.split { it.startsWith('ba') } == [['bar', 'baz'], ['foo']]
+        '''
+    }
+
+    void testInferenceForDGM_sum() {
+        assertScript '''
+            String[] items1 = ['foo','bar','baz']
+            assert items1.sum { it.toUpperCase() } == 'FOOBARBAZ'
+            def items2 = ['fi','fo','fum']
+            assert items2.sum('FEE') { it.toUpperCase() } == 'FEEFIFOFUM'
+        '''
+    }
 
     void testInferenceForDGM_findOnCollection() {
         assertScript '''
@@ -1099,6 +1183,12 @@ import groovy.transform.stc.ClosureParams
             assert ['abc','de','f'].iterator().any { it.length() == 2 }
         '''
     }
+    void testDGM_anyOnArray() {
+        assertScript '''
+            String[] strings = ['abc','de','f']
+            assert strings.any { it.length() == 2 }
+        '''
+    }
 
     void testDGM_mapWithDefault() {
         assertScript '''