Permalink
Switch branches/tags
GROOVY_2_4_3 GROOVY_2_4_2 GROOVY_2_4_1 GROOVY_2_4_0 GROOVY_2_4_0_RC_2 GROOVY_2_4_0_RC_1 GROOVY_2_4_0_BETA_4 GROOVY_2_4_0_BETA_3 GROOVY_2_4_0_BETA_2 GROOVY_2_4_0_BETA_1 GROOVY_2_3_11 GROOVY_2_3_10 GROOVY_2_3_9 GROOVY_2_3_8 GROOVY_2_3_7 GROOVY_2_3_6 GROOVY_2_3_5 GROOVY_2_3_4 GROOVY_2_3_3 GROOVY_2_3_2 GROOVY_2_3_1 GROOVY_2_3_0 GROOVY_2_3_0_RC_4 GROOVY_2_3_0_RC_3 GROOVY_2_3_0_RC_2 GROOVY_2_3_0_RC_1 GROOVY_2_3_0_BETA_2 GROOVY_2_3_0_BETA_1 GROOVY_2_2_2 GROOVY_2_2_1 GROOVY_2_2_0 GROOVY_2_2_0_RC_3 GROOVY_2_2_0_RC_2 GROOVY_2_2_0_RC_1 GROOVY_2_2_0_BETA_1 GROOVY_2_1_9 GROOVY_2_1_8 GROOVY_2_1_7 GROOVY_2_1_6 GROOVY_2_1_5 GROOVY_2_1_4 GROOVY_2_1_3 GROOVY_2_1_2 GROOVY_2_1_1 GROOVY_2_1_0 GROOVY_2_1_0_RC_3 GROOVY_2_1_0_RC_2 GROOVY_2_1_0_RC_1 GROOVY_2_1_0_BETA_1 GROOVY_2_0_8 GROOVY_2_0_7 GROOVY_2_0_6 GROOVY_2_0_5 GROOVY_2_0_4 GROOVY_2_0_2 GROOVY_2_0_1 GROOVY_2_0_0 GROOVY_2_0_0_RC_4 GROOVY_2_0_0_RC_3 GROOVY_2_0_0_RC_2 GROOVY_2_0_0_RC_1 GROOVY_2_0_0_BETA_3 GROOVY_2_0_0_BETA_2 GROOVY_2_0_0_BETA_1 GROOVY_2_0_BETA_2 GROOVY_1_9_BETA_4 GROOVY_1_9_BETA_3 GROOVY_1_9_BETA_1 GROOVY_1_8_9 GROOVY_1_8_8 GROOVY_1_8_7 GROOVY_1_8_6 GROOVY_1_8_5 GROOVY_1_8_4 GROOVY_1_8_3 GROOVY_1_8_2 GROOVY_1_8_1 GROOVY_1_8_0 GROOVY_1_8_0_RC_2 GROOVY_1_8_0_BETA_3 GROOVY_1_8_RC_4 GROOVY_1_8_RC3 GROOVY_1_8_RC_1 GROOVY_1_8_BETA_4 GROOVY_1_8_BETA_2 GROOVY_1_8_BETA_1 GROOVY_1_7_11 GROOVY_1_7_10 GROOVY_1_7_9 GROOVY_1_7_8 GROOVY_1_7_7 GROOVY_1_7_6 GROOVY_1_7_5 GROOVY_1_7_4 GROOVY_1_7_3 GROOVY_1_7_2 GROOVY_1_7_1 GROOVY_1_7_0 GROOVY_1_7_RC_2 GROOVY_1_7_RC1
Nothing to show
Find file Copy path
18168 lines (16791 sloc) 662 KB
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.codehaus.groovy.runtime;
import groovy.io.FileType;
import groovy.io.GroovyPrintWriter;
import groovy.lang.*;
import groovy.transform.stc.ClosureParams;
import groovy.transform.stc.FirstParam;
import groovy.transform.stc.FromString;
import groovy.transform.stc.MapEntryOrKeyValue;
import groovy.transform.stc.SimpleType;
import groovy.util.ClosureComparator;
import groovy.util.GroovyCollections;
import groovy.util.MapEntry;
import groovy.util.OrderBy;
import groovy.util.PermutationGenerator;
import groovy.util.ProxyGenerator;
import org.codehaus.groovy.classgen.Verifier;
import org.codehaus.groovy.reflection.ClassInfo;
import org.codehaus.groovy.reflection.MixinInMetaClass;
import org.codehaus.groovy.reflection.ReflectionCache;
import org.codehaus.groovy.reflection.stdclasses.CachedSAMClass;
import org.codehaus.groovy.runtime.callsite.BooleanClosureWrapper;
import org.codehaus.groovy.runtime.callsite.BooleanReturningMethodInvoker;
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberDiv;
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberMinus;
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberMultiply;
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberPlus;
import org.codehaus.groovy.runtime.dgmimpl.arrays.*;
import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
import org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
import org.codehaus.groovy.runtime.typehandling.GroovyCastException;
import org.codehaus.groovy.runtime.typehandling.NumberMath;
import org.codehaus.groovy.tools.RootLoader;
import org.codehaus.groovy.transform.trait.Traits;
import org.codehaus.groovy.util.ArrayIterator;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This class defines new groovy methods which appear on normal JDK
* classes inside the Groovy environment. Static methods are used with the
* first parameter being the destination class,
* i.e. <code>public static String reverse(String self)</code>
* provides a <code>reverse()</code> method for <code>String</code>.
* <p>
* NOTE: While this class contains many 'public' static methods, it is
* primarily regarded as an internal class (its internal package name
* suggests this also). We value backwards compatibility of these
* methods when used within Groovy but value less backwards compatibility
* at the Java method call level. I.e. future versions of Groovy may
* remove or move a method call in this file but would normally
* aim to keep the method available from within Groovy.
*
* @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
* @author Jeremy Rayner
* @author Sam Pullara
* @author Rod Cope
* @author Guillaume Laforge
* @author John Wilson
* @author Hein Meling
* @author Dierk Koenig
* @author Pilho Kim
* @author Marc Guillemot
* @author Russel Winder
* @author bing ran
* @author Jochen Theodorou
* @author Paul King
* @author Michael Baehr
* @author Joachim Baumann
* @author Alex Tkachman
* @author Ted Naleid
* @author Brad Long
* @author Jim Jagielski
* @author Rodolfo Velasco
* @author jeremi Joslin
* @author Hamlet D'Arcy
* @author Cedric Champeau
* @author Tim Yates
* @author Dinko Srkoc
* @author Andre Steingress
* @author Yu Kobayashi
*/
public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
private static final Logger LOG = Logger.getLogger(DefaultGroovyMethods.class.getName());
private static final Integer ONE = 1;
private static final BigInteger BI_INT_MAX = BigInteger.valueOf(Integer.MAX_VALUE);
private static final BigInteger BI_INT_MIN = BigInteger.valueOf(Integer.MIN_VALUE);
private static final BigInteger BI_LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE);
private static final BigInteger BI_LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE);
public static final Class [] additionals = {
NumberNumberPlus.class,
NumberNumberMultiply.class,
NumberNumberMinus.class,
NumberNumberDiv.class,
ObjectArrayGetAtMetaMethod.class,
ObjectArrayPutAtMetaMethod.class,
BooleanArrayGetAtMetaMethod.class,
BooleanArrayPutAtMetaMethod.class,
ByteArrayGetAtMetaMethod.class,
ByteArrayPutAtMetaMethod.class,
CharacterArrayGetAtMetaMethod.class,
CharacterArrayPutAtMetaMethod.class,
ShortArrayGetAtMetaMethod.class,
ShortArrayPutAtMetaMethod.class,
IntegerArrayGetAtMetaMethod.class,
IntegerArrayPutAtMetaMethod.class,
LongArrayGetAtMetaMethod.class,
LongArrayPutAtMetaMethod.class,
FloatArrayGetAtMetaMethod.class,
FloatArrayPutAtMetaMethod.class,
DoubleArrayGetAtMetaMethod.class,
DoubleArrayPutAtMetaMethod.class,
};
public static final Class[] DGM_LIKE_CLASSES = new Class[]{
DefaultGroovyMethods.class,
DateGroovyMethods.class,
EncodingGroovyMethods.class,
IOGroovyMethods.class,
ProcessGroovyMethods.class,
ResourceGroovyMethods.class,
SocketGroovyMethods.class,
StringGroovyMethods.class//,
// TODO provide alternative way for these to be registered
// SqlGroovyMethods.class,
// SwingGroovyMethods.class,
// XmlGroovyMethods.class,
// NioGroovyMethods.class
};
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
/**
* Identity check. Since == is overridden in Groovy with the meaning of equality
* we need some fallback to check for object identity. Invoke using the
* 'is' method, like so: <code>def same = this.is(that)</code>
*
* @param self an object
* @param other an object to compare identity with
* @return true if self and other are both references to the same
* instance, false otherwise
* @since 1.0
*/
public static boolean is(Object self, Object other) {
return self == other;
}
/**
* Allows the closure to be called for the object reference self.
* Synonym for 'with()'.
*
* @param self the object to have a closure act upon
* @param closure the closure to call on the object
* @return result of calling the closure
* @since 1.0
*/
public static <T> T identity(Object self, Closure<T> closure) {
return DefaultGroovyMethods.with(self, closure);
}
/**
* Allows the closure to be called for the object reference self.
* <p>
* Any method invoked inside the closure will first be invoked on the
* self reference. For instance, the following method calls to the append()
* method are invoked on the StringBuilder instance:
* <pre>
* def b = new StringBuilder().with {
* append('foo')
* append('bar')
* return it
* }
* assert b.toString() == 'foobar'
* </pre>
* This is commonly used to simplify object creation, such as this example:
* <pre>
* def p = new Person().with {
* firstName = 'John'
* lastName = 'Doe'
* return it
* }
* </pre>
*
* @param self the object to have a closure act upon
* @param closure the closure to call on the object
* @return result of calling the closure
* @since 1.5.0
*/
public static <T,U> T with(
@DelegatesTo.Target("self") U self,
@DelegatesTo(value=DelegatesTo.Target.class,
target="self",
strategy=Closure.DELEGATE_FIRST)
@ClosureParams(FirstParam.class)
Closure<T> closure) {
@SuppressWarnings("unchecked")
final Closure<T> clonedClosure = (Closure<T>) closure.clone();
clonedClosure.setResolveStrategy(Closure.DELEGATE_FIRST);
clonedClosure.setDelegate(self);
return clonedClosure.call(self);
}
/**
* Allows the subscript operator to be used to lookup dynamic property values.
* <code>bean[somePropertyNameExpression]</code>. The normal property notation
* of groovy is neater and more concise but only works with compile-time known
* property names.
*
* @param self the object to act upon
* @param property the property name of interest
* @return the property value
* @since 1.0
*/
public static Object getAt(Object self, String property) {
return InvokerHelper.getProperty(self, property);
}
/**
* Allows the subscript operator to be used to set dynamically named property values.
* <code>bean[somePropertyNameExpression] = foo</code>. The normal property notation
* of groovy is neater and more concise but only works with property names which
* are known at compile time.
*
* @param self the object to act upon
* @param property the name of the property to set
* @param newValue the value to set
* @since 1.0
*/
public static void putAt(Object self, String property, Object newValue) {
InvokerHelper.setProperty(self, property, newValue);
}
/**
* Generates a detailed dump string of an object showing its class,
* hashCode and fields.
*
* @param self an object
* @return the dump representation
* @since 1.0
*/
public static String dump(Object self) {
if (self == null) {
return "null";
}
StringBuilder buffer = new StringBuilder("<");
Class klass = self.getClass();
buffer.append(klass.getName());
buffer.append("@");
buffer.append(Integer.toHexString(self.hashCode()));
boolean groovyObject = self instanceof GroovyObject;
/*jes this may be rewritten to use the new getProperties() stuff
* but the original pulls out private variables, whereas getProperties()
* does not. What's the real use of dump() here?
*/
while (klass != null) {
for (final Field field : klass.getDeclaredFields()) {
if ((field.getModifiers() & Modifier.STATIC) == 0) {
if (groovyObject && field.getName().equals("metaClass")) {
continue;
}
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
field.setAccessible(true);
return null;
}
});
buffer.append(" ");
buffer.append(field.getName());
buffer.append("=");
try {
buffer.append(InvokerHelper.toString(field.get(self)));
} catch (Exception e) {
buffer.append(e);
}
}
}
klass = klass.getSuperclass();
}
/* here is a different implementation that uses getProperties(). I have left
* it commented out because it returns a slightly different list of properties;
* i.e. it does not return privates. I don't know what dump() really should be doing,
* although IMO showing private fields is a no-no
*/
/*
List props = getProperties(self);
for(Iterator itr = props.keySet().iterator(); itr.hasNext(); ) {
String propName = itr.next().toString();
// the original skipped this, so I will too
if(pv.getName().equals("class")) continue;
if(pv.getName().equals("metaClass")) continue;
buffer.append(" ");
buffer.append(propName);
buffer.append("=");
try {
buffer.append(InvokerHelper.toString(props.get(propName)));
}
catch (Exception e) {
buffer.append(e);
}
}
*/
buffer.append(">");
return buffer.toString();
}
/**
* Retrieves the list of {@link groovy.lang.MetaProperty} objects for 'self' and wraps it
* in a list of {@link groovy.lang.PropertyValue} objects that additionally provide
* the value for each property of 'self'.
*
* @param self the receiver object
* @return list of {@link groovy.lang.PropertyValue} objects
* @see groovy.util.Expando#getMetaPropertyValues()
* @since 1.0
*/
public static List<PropertyValue> getMetaPropertyValues(Object self) {
MetaClass metaClass = InvokerHelper.getMetaClass(self);
List<MetaProperty> mps = metaClass.getProperties();
List<PropertyValue> props = new ArrayList<PropertyValue>(mps.size());
for (MetaProperty mp : mps) {
props.add(new PropertyValue(self, mp));
}
return props;
}
/**
* Convenience method that calls {@link #getMetaPropertyValues(java.lang.Object)}(self)
* and provides the data in form of simple key/value pairs, i.e.&nsbp;without
* type() information.
*
* @param self the receiver object
* @return meta properties as Map of key/value pairs
* @since 1.0
*/
public static Map getProperties(Object self) {
List<PropertyValue> metaProps = getMetaPropertyValues(self);
Map<String, Object> props = new LinkedHashMap<String, Object>(metaProps.size());
for (PropertyValue mp : metaProps) {
try {
props.put(mp.getName(), mp.getValue());
} catch (Exception e) {
LOG.throwing(self.getClass().getName(), "getProperty(" + mp.getName() + ")", e);
}
}
return props;
}
/**
* Scoped use method
*
* @param self any Object
* @param categoryClass a category class to use
* @param closure the closure to invoke with the category in place
* @return the value returned from the closure
* @since 1.0
*/
public static <T> T use(Object self, Class categoryClass, Closure<T> closure) {
return GroovyCategorySupport.use(categoryClass, closure);
}
/**
* Extend object with category methods.
* All methods for given class and all super classes will be added to the object.
*
* @param self any Class
* @param categoryClasses a category classes to use
* @since 1.6.0
*/
public static void mixin(MetaClass self, List<Class> categoryClasses) {
MixinInMetaClass.mixinClassesToMetaClass(self, categoryClasses);
}
/**
* Extend class globally with category methods.
* All methods for given class and all super classes will be added to the class.
*
* @param self any Class
* @param categoryClasses a category classes to use
* @since 1.6.0
*/
public static void mixin(Class self, List<Class> categoryClasses) {
mixin(getMetaClass(self), categoryClasses);
}
/**
* Extend class globally with category methods.
*
* @param self any Class
* @param categoryClass a category class to use
* @since 1.6.0
*/
public static void mixin(Class self, Class categoryClass) {
mixin(getMetaClass(self), Collections.singletonList(categoryClass));
}
/**
* Extend class globally with category methods.
*
* @param self any Class
* @param categoryClass a category class to use
* @since 1.6.0
*/
public static void mixin(Class self, Class[] categoryClass) {
mixin(getMetaClass(self), Arrays.asList(categoryClass));
}
/**
* Extend class globally with category methods.
*
* @param self any Class
* @param categoryClass a category class to use
* @since 1.6.0
*/
public static void mixin(MetaClass self, Class categoryClass) {
mixin(self, Collections.singletonList(categoryClass));
}
/**
* Extend class globally with category methods.
*
* @param self any Class
* @param categoryClass a category class to use
* @since 1.6.0
*/
public static void mixin(MetaClass self, Class[] categoryClass) {
mixin(self, Arrays.asList(categoryClass));
}
/**
* Scoped use method with list of categories.
*
* @param self any Object
* @param categoryClassList a list of category classes
* @param closure the closure to invoke with the categories in place
* @return the value returned from the closure
* @since 1.0
*/
public static <T> T use(Object self, List<Class> categoryClassList, Closure<T> closure) {
return GroovyCategorySupport.use(categoryClassList, closure);
}
/**
* Allows the usage of addShutdownHook without getting the runtime first.
*
* @param self the object the method is called on (ignored)
* @param closure the shutdown hook action
* @since 1.5.0
*/
public static void addShutdownHook(Object self, Closure closure) {
Runtime.getRuntime().addShutdownHook(new Thread(closure));
}
/**
* Allows you to use a list of categories, specifying the list as varargs.
* <code>use(CategoryClass1, CategoryClass2) { ... }</code>
* This method saves having to wrap the the category
* classes in a list.
*
* @param self any Object
* @param array a list of category classes and a Closure
* @return the value returned from the closure
* @since 1.0
*/
public static Object use(Object self, Object[] array) {
if (array.length < 2)
throw new IllegalArgumentException(
"Expecting at least 2 arguments, a category class and a Closure");
Closure closure;
try {
closure = (Closure) array[array.length - 1];
} catch (ClassCastException e) {
throw new IllegalArgumentException("Expecting a Closure to be the last argument");
}
List<Class> list = new ArrayList<Class>(array.length - 1);
for (int i = 0; i < array.length - 1; ++i) {
Class categoryClass;
try {
categoryClass = (Class) array[i];
} catch (ClassCastException e) {
throw new IllegalArgumentException("Expecting a Category Class for argument " + i);
}
list.add(categoryClass);
}
return GroovyCategorySupport.use(list, closure);
}
/**
* Print a value formatted Groovy style to self if it
* is a Writer, otherwise to the standard output stream.
*
* @param self any Object
* @param value the value to print
* @since 1.0
*/
public static void print(Object self, Object value) {
// we won't get here if we are a PrintWriter
if (self instanceof Writer) {
try {
((Writer) self).write(InvokerHelper.toString(value));
} catch (IOException e) {
// TODO: Should we have some unified function like PrintWriter.checkError()?
}
} else {
System.out.print(InvokerHelper.toString(value));
}
}
/**
* Print a value formatted Groovy style to the print writer.
*
* @param self a PrintWriter
* @param value the value to print
* @since 1.0
*/
public static void print(PrintWriter self, Object value) {
self.print(InvokerHelper.toString(value));
}
/**
* Print a value formatted Groovy style to the print stream.
*
* @param self a PrintStream
* @param value the value to print
* @since 1.6.0
*/
public static void print(PrintStream self, Object value) {
self.print(InvokerHelper.toString(value));
}
/**
* Print a value to the standard output stream.
* This method delegates to the owner to execute the method.
*
* @param self a generated closure
* @param value the value to print
* @since 1.0
*/
public static void print(Closure self, Object value) {
Object owner = getClosureOwner(self);
InvokerHelper.invokeMethod(owner, "print", new Object[]{value});
}
/**
* Print a linebreak to the standard output stream.
*
* @param self any Object
* @since 1.0
*/
public static void println(Object self) {
// we won't get here if we are a PrintWriter
if (self instanceof Writer) {
PrintWriter pw = new GroovyPrintWriter((Writer) self);
pw.println();
} else {
System.out.println();
}
}
/**
* Print a linebreak to the standard output stream.
* This method delegates to the owner to execute the method.
*
* @param self a closure
* @since 1.0
*/
public static void println(Closure self) {
Object owner = getClosureOwner(self);
InvokerHelper.invokeMethod(owner, "println", EMPTY_OBJECT_ARRAY);
}
private static Object getClosureOwner(Closure cls) {
Object owner = cls.getOwner();
while (owner instanceof GeneratedClosure) {
owner = ((Closure) owner).getOwner();
}
return owner;
}
/**
* Print a value formatted Groovy style (followed by a newline) to self
* if it is a Writer, otherwise to the standard output stream.
*
* @param self any Object
* @param value the value to print
* @since 1.0
*/
public static void println(Object self, Object value) {
// we won't get here if we are a PrintWriter
if (self instanceof Writer) {
final PrintWriter pw = new GroovyPrintWriter((Writer) self);
pw.println(value);
} else {
System.out.println(InvokerHelper.toString(value));
}
}
/**
* Print a value formatted Groovy style (followed by a newline) to the print writer.
*
* @param self a PrintWriter
* @param value the value to print
* @since 1.0
*/
public static void println(PrintWriter self, Object value) {
self.println(InvokerHelper.toString(value));
}
/**
* Print a value formatted Groovy style (followed by a newline) to the print stream.
*
* @param self any Object
* @param value the value to print
* @since 1.6.0
*/
public static void println(PrintStream self, Object value) {
self.println(InvokerHelper.toString(value));
}
/**
* Print a value (followed by a newline) to the standard output stream.
* This method delegates to the owner to execute the method.
*
* @param self a closure
* @param value the value to print
* @since 1.0
*/
public static void println(Closure self, Object value) {
Object owner = getClosureOwner(self);
InvokerHelper.invokeMethod(owner, "println", new Object[]{value});
}
/**
* Printf to a console.
*
* @param self any Object
* @param format a format string
* @param values values referenced by the format specifiers in the format string.
* @since 1.0
*/
public static void printf(Object self, String format, Object[] values) {
if (self instanceof PrintStream)
((PrintStream)self).printf(format, values);
else
System.out.printf(format, values);
}
/**
* Sprintf to a string.
*
* @param self any Object
* @param format a format string
* @param values values referenced by the format specifiers in the format string.
* @return the resulting formatted string
* @since 1.5.0
*/
public static String sprintf(Object self, String format, Object[] values) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PrintStream out = new PrintStream(outputStream);
out.printf(format, values);
return outputStream.toString();
}
/**
* Prints a formatted string using the specified format string and
* arguments.
* <p>
* Examples:
* <pre>
* printf ( "Hello, %s!\n" , [ "world" ] as String[] )
* printf ( "Hello, %s!\n" , [ "Groovy" ])
* printf ( "%d + %d = %d\n" , [ 1 , 2 , 1+2 ] as Integer[] )
* printf ( "%d + %d = %d\n" , [ 3 , 3 , 3+3 ])
*
* ( 1..5 ).each { printf ( "-- %d\n" , [ it ] as Integer[] ) }
* ( 1..5 ).each { printf ( "-- %d\n" , [ it ] as int[] ) }
* ( 0x41..0x45 ).each { printf ( "-- %c\n" , [ it ] as char[] ) }
* ( 07..011 ).each { printf ( "-- %d\n" , [ it ] as byte[] ) }
* ( 7..11 ).each { printf ( "-- %d\n" , [ it ] as short[] ) }
* ( 7..11 ).each { printf ( "-- %d\n" , [ it ] as long[] ) }
* ( 7..11 ).each { printf ( "-- %5.2f\n" , [ it ] as float[] ) }
* ( 7..11 ).each { printf ( "-- %5.2g\n" , [ it ] as double[] ) }
* </pre>
*
* @param self any Object
* @param format A format string
* @param arg Argument which is referenced by the format specifiers in the format
* string. The type of <code>arg</code> should be one of Object[], List,
* int[], short[], byte[], char[], boolean[], long[], float[], or double[].
* @since 1.0
*/
public static void printf(Object self, String format, Object arg) {
if (self instanceof PrintStream)
printf((PrintStream) self, format, arg);
else if (self instanceof Writer)
printf((Writer) self, format, arg);
else
printf(System.out, format, arg);
}
private static void printf(PrintStream self, String format, Object arg) {
self.print(sprintf(self, format, arg));
}
private static void printf(Writer self, String format, Object arg) {
try {
self.write(sprintf(self, format, arg));
} catch (IOException e) {
printf(System.out, format, arg);
}
}
/**
* Returns a formatted string using the specified format string and
* arguments.
*
* @param self any Object
* @param format A format string
* @param arg Argument which is referenced by the format specifiers in the format
* string. The type of <code>arg</code> should be one of Object[], List,
* int[], short[], byte[], char[], boolean[], long[], float[], or double[].
* @return the resulting printf'd string
* @since 1.5.0
*/
public static String sprintf(Object self, String format, Object arg) {
if (arg instanceof Object[]) {
return sprintf(self, format, (Object[]) arg);
}
if (arg instanceof List) {
return sprintf(self, format, ((List) arg).toArray());
}
if (!arg.getClass().isArray()) {
Object[] o = (Object[]) java.lang.reflect.Array.newInstance(arg.getClass(), 1);
o[0] = arg;
return sprintf(self, format, o);
}
Object[] ans;
String elemType = arg.getClass().getName();
if (elemType.equals("[I")) {
int[] ia = (int[]) arg;
ans = new Integer[ia.length];
for (int i = 0; i < ia.length; i++) {
ans[i] = ia[i];
}
} else if (elemType.equals("[C")) {
char[] ca = (char[]) arg;
ans = new Character[ca.length];
for (int i = 0; i < ca.length; i++) {
ans[i] = ca[i];
}
} else if (elemType.equals("[Z")) {
boolean[] ba = (boolean[]) arg;
ans = new Boolean[ba.length];
for (int i = 0; i < ba.length; i++) {
ans[i] = ba[i];
}
} else if (elemType.equals("[B")) {
byte[] ba = (byte[]) arg;
ans = new Byte[ba.length];
for (int i = 0; i < ba.length; i++) {
ans[i] = ba[i];
}
} else if (elemType.equals("[S")) {
short[] sa = (short[]) arg;
ans = new Short[sa.length];
for (int i = 0; i < sa.length; i++) {
ans[i] = sa[i];
}
} else if (elemType.equals("[F")) {
float[] fa = (float[]) arg;
ans = new Float[fa.length];
for (int i = 0; i < fa.length; i++) {
ans[i] = fa[i];
}
} else if (elemType.equals("[J")) {
long[] la = (long[]) arg;
ans = new Long[la.length];
for (int i = 0; i < la.length; i++) {
ans[i] = la[i];
}
} else if (elemType.equals("[D")) {
double[] da = (double[]) arg;
ans = new Double[da.length];
for (int i = 0; i < da.length; i++) {
ans[i] = da[i];
}
} else {
throw new RuntimeException("sprintf(String," + arg + ")");
}
return sprintf(self, format, ans);
}
/**
* Inspects returns the String that matches what would be typed into a
* terminal to create this object.
*
* @param self any Object
* @return a String that matches what would be typed into a terminal to
* create this object. e.g. [1, 'hello'].inspect() -> [1, "hello"]
* @since 1.0
*/
public static String inspect(Object self) {
return InvokerHelper.inspect(self);
}
/**
* Print to a console in interactive format.
*
* @param self any Object
* @param out the PrintWriter used for printing
* @since 1.0
*/
public static void print(Object self, PrintWriter out) {
if (out == null) {
out = new PrintWriter(System.out);
}
out.print(InvokerHelper.toString(self));
}
/**
* Print to a console in interactive format.
*
* @param self any Object
* @param out the PrintWriter used for printing
* @since 1.0
*/
public static void println(Object self, PrintWriter out) {
if (out == null) {
out = new PrintWriter(System.out);
}
out.println(InvokerHelper.toString(self));
}
/**
* Provide a dynamic method invocation method which can be overloaded in
* classes to implement dynamic proxies easily.
*
* @param object any Object
* @param method the name of the method to call
* @param arguments the arguments to use
* @return the result of the method call
* @since 1.0
*/
public static Object invokeMethod(Object object, String method, Object arguments) {
return InvokerHelper.invokeMethod(object, method, arguments);
}
// isCase methods
//-------------------------------------------------------------------------
/**
* Method for overloading the behavior of the 'case' method in switch statements.
* The default implementation handles arrays types but otherwise simply delegates
* to Object#equals, but this may be overridden for other types. In this example:
* <pre> switch( a ) {
* case b: //some code
* }</pre>
* "some code" is called when <code>b.isCase( a )</code> returns
* <code>true</code>.
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the switchValue is deemed to be equal to the caseValue
* @since 1.0
*/
public static boolean isCase(Object caseValue, Object switchValue) {
if (caseValue.getClass().isArray()) {
return isCase(DefaultTypeTransformation.asCollection(caseValue), switchValue);
}
return caseValue.equals(switchValue);
}
/**
* Special 'Case' implementation for Class, which allows testing
* for a certain class in a switch statement.
* For example:
* <pre>switch( obj ) {
* case List :
* // obj is a list
* break;
* case Set :
* // etc
* }</pre>
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the switchValue is deemed to be assignable from the given class
* @since 1.0
*/
public static boolean isCase(Class caseValue, Object switchValue) {
if (switchValue instanceof Class) {
Class val = (Class) switchValue;
return caseValue.isAssignableFrom(val);
}
return caseValue.isInstance(switchValue);
}
/**
* 'Case' implementation for collections which tests if the 'switch'
* operand is contained in any of the 'case' values.
* For example:
* <pre class="groovyTestCase">switch( 3 ) {
* case [1,3,5]:
* assert true
* break
* default:
* assert false
* }</pre>
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the caseValue is deemed to contain the switchValue
* @see java.util.Collection#contains(java.lang.Object)
* @since 1.0
*/
public static boolean isCase(Collection caseValue, Object switchValue) {
return caseValue.contains(switchValue);
}
/**
* 'Case' implementation for maps which tests the groovy truth
* value obtained using the 'switch' operand as key.
* For example:
* <pre class="groovyTestCase">switch( 'foo' ) {
* case [foo:true, bar:false]:
* assert true
* break
* default:
* assert false
* }</pre>
*
* @param caseValue the case value
* @param switchValue the switch value
* @return the groovy truth value from caseValue corresponding to the switchValue key
* @since 1.7.6
*/
public static boolean isCase(Map caseValue, Object switchValue) {
return DefaultTypeTransformation.castToBoolean(caseValue.get(switchValue));
}
/**
* Special 'case' implementation for all numbers, which delegates to the
* <code>compareTo()</code> method for comparing numbers of different
* types.
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the numbers are deemed equal
* @since 1.5.0
*/
public static boolean isCase(Number caseValue, Number switchValue) {
return NumberMath.compareTo(caseValue, switchValue) == 0;
}
/**
* Returns an iterator equivalent to this iterator with all duplicated items removed
* by using the default comparator. The original iterator will become
* exhausted of elements after determining the unique values. A new iterator
* for the unique values will be returned.
*
* @param self an Iterator
* @return the modified Iterator
* @since 1.5.5
*/
public static <T> Iterator<T> unique(Iterator<T> self) {
return toList((Iterable<T>) unique(toList(self))).listIterator();
}
/**
* Modifies this collection to remove all duplicated items, using the
* default comparator.
* <pre class="groovyTestCase">assert [1,3] == [1,3,3].unique()</pre>
*
* @param self a collection
* @return the now modified collection
* @see #unique(Collection, boolean)
* @since 1.0
*/
public static <T> Collection<T> unique(Collection<T> self) {
return unique(self, true);
}
/**
* Modifies this List to remove all duplicated items, using the
* default comparator.
* <pre class="groovyTestCase">assert [1,3] == [1,3,3].unique()</pre>
*
* @param self a List
* @return the now modified List
* @see #unique(Collection, boolean)
* @since 2.4.0
*/
public static <T> List<T> unique(List<T> self) {
return (List<T>) unique((Collection<T>) self, true);
}
/**
* Remove all duplicates from a given Collection using the default comparator.
* If mutate is true, it works by modifying the original object (and also returning it).
* If mutate is false, a new collection is returned leaving the original unchanged.
* <pre class="groovyTestCase">
* assert [1,3] == [1,3,3].unique()
* </pre>
* <pre class="groovyTestCase">
* def orig = [1, 3, 2, 3]
* def uniq = orig.unique(false)
* assert orig == [1, 3, 2, 3]
* assert uniq == [1, 3, 2]
* </pre>
*
* @param self a collection
* @param mutate false will cause a new list containing unique items from the collection to be created, true will mutate collections in place
* @return the now modified collection
* @since 1.8.1
*/
public static <T> Collection<T> unique(Collection<T> self, boolean mutate) {
List<T> answer = new ArrayList<T>();
for (T t : self) {
boolean duplicated = false;
for (T t2 : answer) {
if (coercedEquals(t, t2)) {
duplicated = true;
break;
}
}
if (!duplicated)
answer.add(t);
}
if (mutate) {
self.clear();
self.addAll(answer);
}
return mutate ? self : answer ;
}
/**
* Remove all duplicates from a given List using the default comparator.
* If mutate is true, it works by modifying the original object (and also returning it).
* If mutate is false, a new collection is returned leaving the original unchanged.
* <pre class="groovyTestCase">
* assert [1,3] == [1,3,3].unique()
* </pre>
* <pre class="groovyTestCase">
* def orig = [1, 3, 2, 3]
* def uniq = orig.unique(false)
* assert orig == [1, 3, 2, 3]
* assert uniq == [1, 3, 2]
* </pre>
*
* @param self a List
* @param mutate false will cause a new List containing unique items from the List to be created, true will mutate List in place
* @return the now modified List
* @since 2.4.0
*/
public static <T> List<T> unique(List<T> self, boolean mutate) {
return (List<T>) unique((Collection<T>) self, mutate);
}
/**
* Provides a method that compares two comparables using Groovy's
* default number aware comparator.
*
* @param self a Comparable
* @param other another Comparable
* @return a -ve number, 0 or a +ve number according to Groovy's compareTo contract
* @since 1.6.0
*/
public static int numberAwareCompareTo(Comparable self, Comparable other) {
NumberAwareComparator<Comparable> numberAwareComparator = new NumberAwareComparator<Comparable>();
return numberAwareComparator.compare(self, other);
}
/**
* Returns an iterator equivalent to this iterator but with all duplicated items
* removed by using a Closure to determine duplicate (equal) items.
* The original iterator will be fully processed after the call.
* <p>
* If the closure takes a single parameter, the argument passed will be each element,
* and the closure should return a value used for comparison (either using
* {@link java.lang.Comparable#compareTo(java.lang.Object)} or {@link java.lang.Object#equals(java.lang.Object)}).
* If the closure takes two parameters, two items from the Iterator
* will be passed as arguments, and the closure should return an
* int value (with 0 indicating the items are not unique).
*
* @param self an Iterator
* @param closure a Closure used to determine unique items
* @return the modified Iterator
* @since 1.5.5
*/
public static <T> Iterator<T> unique(Iterator<T> self, @ClosureParams(value=FromString.class, options={"T","T,T"}) Closure closure) {
return toList((Iterable<T>) unique(toList(self), closure)).listIterator();
}
/**
* A convenience method for making a collection unique using a Closure
* to determine duplicate (equal) items.
* <p>
* If the closure takes a single parameter, the
* argument passed will be each element, and the closure
* should return a value used for comparison (either using
* {@link java.lang.Comparable#compareTo(java.lang.Object)} or {@link java.lang.Object#equals(java.lang.Object)}).
* If the closure takes two parameters, two items from the collection
* will be passed as arguments, and the closure should return an
* int value (with 0 indicating the items are not unique).
* <pre class="groovyTestCase">assert [1,4] == [1,3,4,5].unique { it % 2 }</pre>
* <pre class="groovyTestCase">assert [2,3,4] == [2,3,3,4].unique { a, b -> a <=> b }</pre>
*
* @param self a Collection
* @param closure a 1 or 2 arg Closure used to determine unique items
* @return self without any duplicates
* @see #unique(Collection, boolean, Closure)
* @since 1.0
*/
public static <T> Collection<T> unique(Collection<T> self, @ClosureParams(value=FromString.class, options={"T","T,T"}) Closure closure) {
return unique(self, true, closure);
}
/**
* A convenience method for making a List unique using a Closure
* to determine duplicate (equal) items.
* <p>
* If the closure takes a single parameter, the
* argument passed will be each element, and the closure
* should return a value used for comparison (either using
* {@link java.lang.Comparable#compareTo(java.lang.Object)} or {@link java.lang.Object#equals(java.lang.Object)}).
* If the closure takes two parameters, two items from the List
* will be passed as arguments, and the closure should return an
* int value (with 0 indicating the items are not unique).
* <pre class="groovyTestCase">assert [1,4] == [1,3,4,5].unique { it % 2 }</pre>
* <pre class="groovyTestCase">assert [2,3,4] == [2,3,3,4].unique { a, b -> a <=> b }</pre>
*
* @param self a List
* @param closure a 1 or 2 arg Closure used to determine unique items
* @return self without any duplicates
* @see #unique(Collection, boolean, Closure)
* @since 2.4.0
*/
public static <T> List<T> unique(List<T> self, @ClosureParams(value=FromString.class, options={"T","T,T"}) Closure closure) {
return (List<T>) unique((Collection<T>) self, true, closure);
}
/**
* A convenience method for making a collection unique using a Closure to determine duplicate (equal) items.
* If mutate is true, it works on the receiver object and returns it. If mutate is false, a new collection is returned.
* <p>
* If the closure takes a single parameter, each element from the Collection will be passed to the closure. The closure
* should return a value used for comparison (either using {@link java.lang.Comparable#compareTo(java.lang.Object)} or
* {@link java.lang.Object#equals(java.lang.Object)}). If the closure takes two parameters, two items from the collection
* will be passed as arguments, and the closure should return an int value (with 0 indicating the items are not unique).
* <pre class="groovyTestCase">
* def orig = [1, 3, 4, 5]
* def uniq = orig.unique(false) { it % 2 }
* assert orig == [1, 3, 4, 5]
* assert uniq == [1, 4]
* </pre>
* <pre class="groovyTestCase">
* def orig = [2, 3, 3, 4]
* def uniq = orig.unique(false) { a, b -> a <=> b }
* assert orig == [2, 3, 3, 4]
* assert uniq == [2, 3, 4]
* </pre>
*
* @param self a Collection
* @param mutate false will always cause a new list to be created, true will mutate lists in place
* @param closure a 1 or 2 arg Closure used to determine unique items
* @return self without any duplicates
* @since 1.8.1
*/
public static <T> Collection<T> unique(Collection<T> self, boolean mutate, @ClosureParams(value=FromString.class, options={"T","T,T"}) Closure closure) {
// use a comparator of one item or two
int params = closure.getMaximumNumberOfParameters();
if (params == 1) {
self = unique(self, mutate, new OrderBy<T>(closure, true));
} else {
self = unique(self, mutate, new ClosureComparator<T>(closure));
}
return self;
}
/**
* A convenience method for making a List unique using a Closure to determine duplicate (equal) items.
* If mutate is true, it works on the receiver object and returns it. If mutate is false, a new collection is returned.
* <p>
* If the closure takes a single parameter, each element from the List will be passed to the closure. The closure
* should return a value used for comparison (either using {@link java.lang.Comparable#compareTo(java.lang.Object)} or
* {@link java.lang.Object#equals(java.lang.Object)}). If the closure takes two parameters, two items from the collection
* will be passed as arguments, and the closure should return an int value (with 0 indicating the items are not unique).
* <pre class="groovyTestCase">
* def orig = [1, 3, 4, 5]
* def uniq = orig.unique(false) { it % 2 }
* assert orig == [1, 3, 4, 5]
* assert uniq == [1, 4]
* </pre>
* <pre class="groovyTestCase">
* def orig = [2, 3, 3, 4]
* def uniq = orig.unique(false) { a, b -> a <=> b }
* assert orig == [2, 3, 3, 4]
* assert uniq == [2, 3, 4]
* </pre>
*
* @param self a List
* @param mutate false will always cause a new list to be created, true will mutate lists in place
* @param closure a 1 or 2 arg Closure used to determine unique items
* @return self without any duplicates
* @since 2.4.0
*/
public static <T> List<T> unique(List<T> self, boolean mutate, @ClosureParams(value=FromString.class, options={"T","T,T"}) Closure closure) {
return (List<T>) unique((Collection<T>) self, mutate, closure);
}
/**
* Returns an iterator equivalent to this iterator with all duplicated
* items removed by using the supplied comparator.
*
* @param self an Iterator
* @param comparator a Comparator
* @return the modified Iterator
* @since 1.5.5
*/
public static <T> Iterator<T> unique(Iterator<T> self, Comparator<T> comparator) {
return toList((Iterable<T>) unique(toList(self), comparator)).listIterator();
}
/**
* Remove all duplicates from a given Collection.
* Works on the original object (and also returns it).
* The order of members in the Collection are compared by the given Comparator.
* For each duplicate, the first member which is returned
* by the given Collection's iterator is retained, but all other ones are removed.
* The given Collection's original order is preserved.
* <p>
* <pre class="groovyTestCase">
* class Person {
* def fname, lname
* String toString() {
* return fname + " " + lname
* }
* }
*
* class PersonComparator implements Comparator {
* int compare(Object o1, Object o2) {
* Person p1 = (Person) o1
* Person p2 = (Person) o2
* if (p1.lname != p2.lname)
* return p1.lname.compareTo(p2.lname)
* else
* return p1.fname.compareTo(p2.fname)
* }
*
* boolean equals(Object obj) {
* return this.equals(obj)
* }
* }
*
* Person a = new Person(fname:"John", lname:"Taylor")
* Person b = new Person(fname:"Clark", lname:"Taylor")
* Person c = new Person(fname:"Tom", lname:"Cruz")
* Person d = new Person(fname:"Clark", lname:"Taylor")
*
* def list = [a, b, c, d]
* List list2 = list.unique(new PersonComparator())
* assert( list2 == list && list == [a, b, c] )
* </pre>
*
* @param self a Collection
* @param comparator a Comparator
* @return self the now modified collection without duplicates
* @see #unique(java.util.Collection, boolean, java.util.Comparator)
* @since 1.0
*/
public static <T> Collection<T> unique(Collection<T> self, Comparator<T> comparator) {
return unique(self, true, comparator) ;
}
/**
* Remove all duplicates from a given List.
* Works on the original object (and also returns it).
* The order of members in the List are compared by the given Comparator.
* For each duplicate, the first member which is returned
* by the given List's iterator is retained, but all other ones are removed.
* The given List's original order is preserved.
* <p>
* <pre class="groovyTestCase">
* class Person {
* def fname, lname
* String toString() {
* return fname + " " + lname
* }
* }
*
* class PersonComparator implements Comparator {
* int compare(Object o1, Object o2) {
* Person p1 = (Person) o1
* Person p2 = (Person) o2
* if (p1.lname != p2.lname)
* return p1.lname.compareTo(p2.lname)
* else
* return p1.fname.compareTo(p2.fname)
* }
*
* boolean equals(Object obj) {
* return this.equals(obj)
* }
* }
*
* Person a = new Person(fname:"John", lname:"Taylor")
* Person b = new Person(fname:"Clark", lname:"Taylor")
* Person c = new Person(fname:"Tom", lname:"Cruz")
* Person d = new Person(fname:"Clark", lname:"Taylor")
*
* def list = [a, b, c, d]
* List list2 = list.unique(new PersonComparator())
* assert( list2 == list && list == [a, b, c] )
* </pre>
*
* @param self a List
* @param comparator a Comparator
* @return self the now modified List without duplicates
* @see #unique(java.util.Collection, boolean, java.util.Comparator)
* @since 2.4.0
*/
public static <T> List<T> unique(List<T> self, Comparator<T> comparator) {
return (List<T>) unique((Collection<T>) self, true, comparator);
}
/**
* Remove all duplicates from a given Collection.
* If mutate is true, it works on the original object (and also returns it). If mutate is false, a new collection is returned.
* The order of members in the Collection are compared by the given Comparator.
* For each duplicate, the first member which is returned
* by the given Collection's iterator is retained, but all other ones are removed.
* The given Collection's original order is preserved.
* <p>
* <pre class="groovyTestCase">
* class Person {
* def fname, lname
* String toString() {
* return fname + " " + lname
* }
* }
*
* class PersonComparator implements Comparator {
* int compare(Object o1, Object o2) {
* Person p1 = (Person) o1
* Person p2 = (Person) o2
* if (p1.lname != p2.lname)
* return p1.lname.compareTo(p2.lname)
* else
* return p1.fname.compareTo(p2.fname)
* }
*
* boolean equals(Object obj) {
* return this.equals(obj)
* }
* }
*
* Person a = new Person(fname:"John", lname:"Taylor")
* Person b = new Person(fname:"Clark", lname:"Taylor")
* Person c = new Person(fname:"Tom", lname:"Cruz")
* Person d = new Person(fname:"Clark", lname:"Taylor")
*
* def list = [a, b, c, d]
* List list2 = list.unique(false, new PersonComparator())
* assert( list2 != list && list2 == [a, b, c] )
* </pre>
*
* @param self a Collection
* @param mutate false will always cause a new collection to be created, true will mutate collections in place
* @param comparator a Comparator
* @return self the collection without duplicates
* @since 1.8.1
*/
public static <T> Collection<T> unique(Collection<T> self, boolean mutate, Comparator<T> comparator) {
List<T> answer = new ArrayList<T>();
for (T t : self) {
boolean duplicated = false;
for (T t2 : answer) {
if (comparator.compare(t, t2) == 0) {
duplicated = true;
break;
}
}
if (!duplicated)
answer.add(t);
}
if (mutate) {
self.clear();
self.addAll(answer);
}
return mutate ? self : answer;
}
/**
* Remove all duplicates from a given List.
* If mutate is true, it works on the original object (and also returns it). If mutate is false, a new List is returned.
* The order of members in the List are compared by the given Comparator.
* For each duplicate, the first member which is returned
* by the given List's iterator is retained, but all other ones are removed.
* The given List's original order is preserved.
* <p>
* <pre class="groovyTestCase">
* class Person {
* def fname, lname
* String toString() {
* return fname + " " + lname
* }
* }
*
* class PersonComparator implements Comparator {
* int compare(Object o1, Object o2) {
* Person p1 = (Person) o1
* Person p2 = (Person) o2
* if (p1.lname != p2.lname)
* return p1.lname.compareTo(p2.lname)
* else
* return p1.fname.compareTo(p2.fname)
* }
*
* boolean equals(Object obj) {
* return this.equals(obj)
* }
* }
*
* Person a = new Person(fname:"John", lname:"Taylor")
* Person b = new Person(fname:"Clark", lname:"Taylor")
* Person c = new Person(fname:"Tom", lname:"Cruz")
* Person d = new Person(fname:"Clark", lname:"Taylor")
*
* def list = [a, b, c, d]
* List list2 = list.unique(false, new PersonComparator())
* assert( list2 != list && list2 == [a, b, c] )
* </pre>
*
* @param self a List
* @param mutate false will always cause a new List to be created, true will mutate List in place
* @param comparator a Comparator
* @return self the List without duplicates
* @since 2.4.0
*/
public static <T> List<T> unique(List<T> self, boolean mutate, Comparator<T> comparator) {
return (List<T>) unique((Collection<T>) self, mutate, comparator);
}
/**
* Returns an iterator equivalent to this iterator but with all duplicated items
* removed where duplicate (equal) items are deduced by calling the supplied Closure condition.
* <p>
* If the supplied Closure takes a single parameter, the argument passed will be each element,
* and the closure should return a value used for comparison (either using
* {@link java.lang.Comparable#compareTo(java.lang.Object)} or {@link java.lang.Object#equals(java.lang.Object)}).
* If the closure takes two parameters, two items from the Iterator
* will be passed as arguments, and the closure should return an
* int value (with 0 indicating the items are not unique).
* <pre class="groovyTestCase">
* def items = "Hello".toList() + [null, null] + "there".toList()
* def toLower = { it == null ? null : it.toLowerCase() }
* def noDups = items.iterator().toUnique(toLower).toList()
* assert noDups == ['H', 'e', 'l', 'o', null, 't', 'r']
* </pre>
* <pre class="groovyTestCase">assert [1,4] == [1,3,4,5].toUnique { it % 2 }</pre>
* <pre class="groovyTestCase">assert [2,3,4] == [2,3,3,4].toUnique { a, b -> a <=> b }</pre>
*
* @param self an Iterator
* @param condition a Closure used to determine unique items
* @return an Iterator with no duplicate items
* @since 2.4.0
*/
public static <T> Iterator<T> toUnique(Iterator<T> self, @ClosureParams(value=FromString.class, options={"T","T,T"}) Closure condition) {
return new UniqueIterator<T>(self, condition.getMaximumNumberOfParameters() == 1
? new OrderBy<T>(condition, true)
: new ClosureComparator<T>(condition));
}
private static final class UniqueIterator<E> implements Iterator<E> {
private final Iterator<E> delegate;
private final Set<E> seen;
private boolean exhausted;
private E next;
private UniqueIterator(Iterator<E> delegate, Comparator<E> comparator) {
this.delegate = delegate;
seen = new TreeSet<E>(comparator);
advance();
}
public boolean hasNext() {
return !exhausted;
}
public E next() {
if (exhausted) throw new NoSuchElementException();
E result = next;
advance();
return result;
}
public void remove() {
if (exhausted) throw new NoSuchElementException();
delegate.remove();
}
private void advance() {
boolean foundNext = false;
while (!foundNext && !exhausted) {
exhausted = !delegate.hasNext();
if (!exhausted) {
next = delegate.next();
foundNext = seen.add(next);
}
}
}
}
/**
* Returns an iterator equivalent to this iterator with all duplicated
* items removed by using the supplied comparator.
*
* @param self an Iterator
* @param comparator a Comparator used to determine unique (equal) items
* If {@code null}, the Comparable natural ordering of the elements will be used.
* @return an Iterator with no duplicate items
* @since 2.4.0
*/
public static <T> Iterator<T> toUnique(Iterator<T> self, Comparator<T> comparator) {
return new UniqueIterator<T>(self, comparator);
}
/**
* Returns an iterator equivalent to this iterator with all duplicated
* items removed by using the natural ordering of the items.
*
* @param self an Iterator
* @return an Iterator with no duplicate items
* @since 2.4.0
*/
public static <T> Iterator<T> toUnique(Iterator<T> self) {
return new UniqueIterator<T>(self, null);
}
/**
* Returns a Collection containing the items from the Iterable but with duplicates removed.
* The items in the Iterable are compared by the given Comparator.
* For each duplicate, the first member which is returned from the
* Iterable is retained, but all other ones are removed.
* <p>
* <pre class="groovyTestCase">
* class Person {
* def fname, lname
* String toString() {
* return fname + " " + lname
* }
* }
*
* class PersonComparator implements Comparator {
* int compare(Object o1, Object o2) {
* Person p1 = (Person) o1
* Person p2 = (Person) o2
* if (p1.lname != p2.lname)
* return p1.lname.compareTo(p2.lname)
* else
* return p1.fname.compareTo(p2.fname)
* }
*
* boolean equals(Object obj) {
* return this.equals(obj)
* }
* }
*
* Person a = new Person(fname:"John", lname:"Taylor")
* Person b = new Person(fname:"Clark", lname:"Taylor")
* Person c = new Person(fname:"Tom", lname:"Cruz")
* Person d = new Person(fname:"Clark", lname:"Taylor")
*
* def list = [a, b, c, d]
* List list2 = list.toUnique(new PersonComparator())
* assert( list2 == list && list == [a, b, c] )
* </pre>
*
* @param self an Iterable
* @param comparator a Comparator used to determine unique (equal) items
* If {@code null}, the Comparable natural ordering of the elements will be used.
* @return the Collection of non-duplicate items
* @since 2.4.0
*/
public static <T> Collection<T> toUnique(Iterable<T> self, Comparator<T> comparator) {
Collection<T> result = createSimilarCollection((Collection<T>) self);
addAll(result, toUnique(self.iterator(), comparator));
return result;
}
/**
* Returns a List containing the items from the List but with duplicates removed.
* The items in the List are compared by the given Comparator.
* For each duplicate, the first member which is returned from the
* List is retained, but all other ones are removed.
* <p>
* <pre class="groovyTestCase">
* class Person {
* def fname, lname
* String toString() {
* return fname + " " + lname
* }
* }
*
* class PersonComparator implements Comparator {
* int compare(Object o1, Object o2) {
* Person p1 = (Person) o1
* Person p2 = (Person) o2
* if (p1.lname != p2.lname)
* return p1.lname.compareTo(p2.lname)
* else
* return p1.fname.compareTo(p2.fname)
* }
*
* boolean equals(Object obj) {
* return this.equals(obj)
* }
* }
*
* Person a = new Person(fname:"John", lname:"Taylor")
* Person b = new Person(fname:"Clark", lname:"Taylor")
* Person c = new Person(fname:"Tom", lname:"Cruz")
* Person d = new Person(fname:"Clark", lname:"Taylor")
*
* def list = [a, b, c, d]
* List list2 = list.toUnique(new PersonComparator())
* assert( list2 == list && list == [a, b, c] )
* </pre>
*
* @param self an List
* @param comparator a Comparator used to determine unique (equal) items
* If {@code null}, the Comparable natural ordering of the elements will be used.
* @return the List of non-duplicate items
* @since 2.4.0
*/
public static <T> List<T> toUnique(List<T> self, Comparator<T> comparator) {
return (List<T>) toUnique((Iterable<T>) self, comparator);
}
/**
* Returns a Collection containing the items from the Iterable but with duplicates removed
* using the natural ordering of the items to determine uniqueness.
* <p>
* <pre class="groovyTestCase">
* String[] letters = ['c', 'a', 't', 's', 'a', 't', 'h', 'a', 't']
* String[] expected = ['c', 'a', 't', 's', 'h']
* assert letters.toUnique() == expected
* </pre>
*
* @param self an Iterable
* @return the Collection of non-duplicate items
* @since 2.4.0
*/
public static <T> Collection<T> toUnique(Iterable<T> self) {
return toUnique(self, (Comparator<T>) null);
}
/**
* Returns a List containing the items from the List but with duplicates removed
* using the natural ordering of the items to determine uniqueness.
* <p>
* <pre class="groovyTestCase">
* def letters = ['c', 'a', 't', 's', 'a', 't', 'h', 'a', 't']
* def expected = ['c', 'a', 't', 's', 'h']
* assert letters.toUnique() == expected
* </pre>
*
* @param self an List
* @return the List of non-duplicate items
* @since 2.4.0
*/
public static <T> List<T> toUnique(List<T> self) {
return toUnique(self, (Comparator<T>) null);
}
/**
* Returns a Collection containing the items from the Iterable but with duplicates removed.
* The items in the Iterable are compared by the given Closure condition.
* For each duplicate, the first member which is returned from the
* Iterable is retained, but all other ones are removed.
* <p>
* If the closure takes a single parameter, each element from the Iterable will be passed to the closure. The closure
* should return a value used for comparison (either using {@link java.lang.Comparable#compareTo(java.lang.Object)} or
* {@link java.lang.Object#equals(java.lang.Object)}). If the closure takes two parameters, two items from the Iterable
* will be passed as arguments, and the closure should return an int value (with 0 indicating the items are not unique).
* <p>
* <pre class="groovyTestCase">
* class Person {
* def fname, lname
* String toString() {
* return fname + " " + lname
* }
* }
*
* Person a = new Person(fname:"John", lname:"Taylor")
* Person b = new Person(fname:"Clark", lname:"Taylor")
* Person c = new Person(fname:"Tom", lname:"Cruz")
* Person d = new Person(fname:"Clark", lname:"Taylor")
*
* def list = [a, b, c, d]
* def list2 = list.toUnique{ p1, p2 -> p1.lname != p2.lname ? p1.lname &lt;=&gt; p2.lname : p1.fname &lt;=&gt; p2.fname }
* assert( list2 == [a, b, c] && list == [a, b, c, d] )
* def list3 = list.toUnique{ it.toString() }
* assert( list3 == [a, b, c] && list == [a, b, c, d] )
* </pre>
*
* @param self an Iterable
* @param condition a Closure used to determine unique items
* @return a new Collection
* @see #toUnique(Iterable, Comparator)
* @since 2.4.0
*/
public static <T> Collection<T> toUnique(Iterable<T> self, @ClosureParams(value = FromString.class, options = {"T", "T,T"}) Closure condition) {
Comparator<T> comparator = condition.getMaximumNumberOfParameters() == 1
? new OrderBy<T>(condition, true)
: new ClosureComparator<T>(condition);
return toUnique(self, comparator);
}
/**
* Returns a List containing the items from the List but with duplicates removed.
* The items in the List are compared by the given Closure condition.
* For each duplicate, the first member which is returned from the
* Iterable is retained, but all other ones are removed.
* <p>
* If the closure takes a single parameter, each element from the Iterable will be passed to the closure. The closure
* should return a value used for comparison (either using {@link java.lang.Comparable#compareTo(java.lang.Object)} or
* {@link java.lang.Object#equals(java.lang.Object)}). If the closure takes two parameters, two items from the Iterable
* will be passed as arguments, and the closure should return an int value (with 0 indicating the items are not unique).
* <p>
* <pre class="groovyTestCase">
* class Person {
* def fname, lname
* String toString() {
* return fname + " " + lname
* }
* }
*
* Person a = new Person(fname:"John", lname:"Taylor")
* Person b = new Person(fname:"Clark", lname:"Taylor")
* Person c = new Person(fname:"Tom", lname:"Cruz")
* Person d = new Person(fname:"Clark", lname:"Taylor")
*
* def list = [a, b, c, d]
* def list2 = list.toUnique{ p1, p2 -> p1.lname != p2.lname ? p1.lname &lt;=&gt; p2.lname : p1.fname &lt;=&gt; p2.fname }
* assert( list2 == [a, b, c] && list == [a, b, c, d] )
* def list3 = list.toUnique{ it.toString() }
* assert( list3 == [a, b, c] && list == [a, b, c, d] )
* </pre>
*
* @param self a List
* @param condition a Closure used to determine unique items
* @return a new List
* @see #toUnique(Iterable, Comparator)
* @since 2.4.0
*/
public static <T> List<T> toUnique(List<T> self, @ClosureParams(value = FromString.class, options = {"T", "T,T"}) Closure condition) {
return (List<T>) toUnique((Iterable<T>) self, condition);
}
/**
* Returns a new Array containing the items from the original Array but with duplicates removed with the supplied
* comparator determining which items are unique.
* <p>
* <pre class="groovyTestCase">
* String[] letters = ['c', 'a', 't', 's', 'A', 't', 'h', 'a', 'T']
* String[] lower = ['c', 'a', 't', 's', 'h']
* class LowerComparator implements Comparator {
* int compare(let1, let2) { let1.toLowerCase() <=> let2.toLowerCase() }
* }
* assert letters.toUnique(new LowerComparator()) == lower
* </pre>
*
* @param self an array
* @param comparator a Comparator used to determine unique (equal) items
* If {@code null}, the Comparable natural ordering of the elements will be used.
* @return the unique items from the array
*/
@SuppressWarnings("unchecked")
public static <T> T[] toUnique(T[] self, Comparator<T> comparator) {
Collection<T> items = toUnique(toList(self), comparator);
T[] result = createSimilarArray(self, items.size());
return items.toArray(result);
}
/**
* Returns a new Array containing the items from the original Array but with duplicates removed using the
* natural ordering of the items in the array.
* <p>
* <pre class="groovyTestCase">
* String[] letters = ['c', 'a', 't', 's', 'a', 't', 'h', 'a', 't']
* String[] expected = ['c', 'a', 't', 's', 'h']
* def result = letters.toUnique()
* assert result == expected
* assert result.class.componentType == String
* </pre>
*
* @param self an array
* @return the unique items from the array
*/
@SuppressWarnings("unchecked")
public static <T> T[] toUnique(T[] self) {
return (T[]) toUnique(self, (Comparator) null);
}
/**
* Returns a new Array containing the items from the original Array but with duplicates removed with the supplied
* comparator determining which items are unique.
* <p>
* <pre class="groovyTestCase">
* String[] letters = ['c', 'a', 't', 's', 'A', 't', 'h', 'a', 'T']
* String[] expected = ['c', 'a', 't', 's', 'h']
* assert letters.toUnique{ p1, p2 -> p1.toLowerCase() <=> p2.toLowerCase() } == expected
* assert letters.toUnique{ it.toLowerCase() } == expected
* </pre>
*
* @param self an array
* @param condition a Closure used to determine unique items
* @return the unique items from the array
*/
@SuppressWarnings("unchecked")
public static <T> T[] toUnique(T[] self, @ClosureParams(value=FromString.class, options={"T","T,T"}) Closure condition) {
Comparator<T> comparator = condition.getMaximumNumberOfParameters() == 1
? new OrderBy<T>(condition, true)
: new ClosureComparator<T>(condition);
return toUnique(self, comparator);
}
/**
* Iterates through an aggregate type or data structure,
* passing each item to the given closure. Custom types may utilize this
* method by simply providing an "iterator()" method. The items returned
* from the resulting iterator will be passed to the closure.
*
* @param self the object over which we iterate
* @param closure the closure applied on each element found
* @return the self Object
* @since 1.0
*/
public static <T> T each(T self, Closure closure) {
each(InvokerHelper.asIterator(self), closure);
return self;
}
/**
* Iterates through an aggregate type or data structure,
* passing each item and the item's index (a counter starting at
* zero) to the given closure.
*
* @param self an Object
* @param closure a Closure to operate on each item
* @return the self Object
* @since 1.0
*/
public static <T> T eachWithIndex(T self, Closure closure) {
final Object[] args = new Object[2];
int counter = 0;
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
args[0] = iter.next();
args[1] = counter++;
closure.call(args);
}
return self;
}
/**
* Iterates through an iterable type,
* passing each item and the item's index (a counter starting at
* zero) to the given closure.
*
* @param self an Iterable
* @param closure a Closure to operate on each item
* @return the self Iterable
* @since 2.3.0
*/
public static <T> Iterable<T> eachWithIndex(Iterable<T> self, @ClosureParams(value=FromString.class, options="T,Integer") Closure closure) {
eachWithIndex(self.iterator(), closure);
return self;
}
/**
* Iterates through an iterator type,
* passing each item and the item's index (a counter starting at
* zero) to the given closure.
*
* @param self an Iterable
* @param closure a Closure to operate on each item
* @return the self Iterable
* @since 2.3.0
*/
public static <T> Iterator<T> eachWithIndex(Iterator<T> self, @ClosureParams(value=FromString.class, options="T,Integer") Closure closure) {
final Object[] args = new Object[2];
int counter = 0;
while (self.hasNext()) {
args[0] = self.next();
args[1] = counter++;
closure.call(args);
}
return self;
}
/**
* Iterates through an Collection,
* passing each item and the item's index (a counter starting at
* zero) to the given closure.
*
* @param self an Collection
* @param closure a Closure to operate on each item
* @return the self Collection
* @since 2.4.0
*/
public static <T> Collection<T> eachWithIndex(Collection<T> self, @ClosureParams(value=FromString.class, options="T,Integer") Closure closure) {
return (Collection<T>) eachWithIndex((Iterable<T>) self, closure);
}
/**
* Iterates through an List,
* passing each item and the item's index (a counter starting at
* zero) to the given closure.
*
* @param self an List
* @param closure a Closure to operate on each item
* @return the self List
* @since 2.4.0
*/
public static <T> List<T> eachWithIndex(List<T> self, @ClosureParams(value=FromString.class, options="T,Integer") Closure closure) {
return (List<T>) eachWithIndex((Iterable<T>) self, closure);
}
/**
* Iterates through an Set,
* passing each item and the item's index (a counter starting at
* zero) to the given closure.
*
* @param self an Set
* @param closure a Closure to operate on each item
* @return the self Set
* @since 2.4.0
*/
public static <T> Set<T> eachWithIndex(Set<T> self, @ClosureParams(value=FromString.class, options="T,Integer") Closure closure) {
return (Set<T>) eachWithIndex((Iterable<T>) self, closure);
}
/**
* Iterates through an SortedSet,
* passing each item and the item's index (a counter starting at
* zero) to the given closure.
*
* @param self an SortedSet
* @param closure a Closure to operate on each item
* @return the self SortedSet
* @since 2.4.0
*/
public static <T> SortedSet<T> eachWithIndex(SortedSet<T> self, @ClosureParams(value=FromString.class, options="T,Integer") Closure closure) {
return (SortedSet<T>) eachWithIndex((Iterable<T>) self, closure);
}
/**
* Iterates through an Iterable, passing each item to the given closure.
*
* @param self the Iterable over which we iterate
* @param closure the closure applied on each element found
* @return the self Iterable
*/
public static <T> Iterable<T> each(Iterable<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
each(self.iterator(), closure);
return self;
}
/**
* Iterates through an Iterator, passing each item to the given closure.
*
* @param self the Iterator over which we iterate
* @param closure the closure applied on each element found
* @return the self Iterator
* @since 2.4.0
*/
public static <T> Iterator<T> each(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
while (self.hasNext()) {
Object arg = self.next();
closure.call(arg);
}
return self;
}
/**
* Iterates through an Collection, passing each item to the given closure.
*
* @param self the Collection over which we iterate
* @param closure the closure applied on each element found
* @return the self Collection
* @since 2.4.0
*/
public static <T> Collection<T> each(Collection<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
return (Collection<T>) each((Iterable<T>) self, closure);
}
/**
* Iterates through an List, passing each item to the given closure.
*
* @param self the List over which we iterate
* @param closure the closure applied on each element found
* @return the self List
* @since 2.4.0
*/
public static <T> List<T> each(List<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
return (List<T>) each((Iterable<T>) self, closure);
}
/**
* Iterates through an Set, passing each item to the given closure.
*
* @param self the Set over which we iterate
* @param closure the closure applied on each element found
* @return the self Set
* @since 2.4.0
*/
public static <T> Set<T> each(Set<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
return (Set<T>) each((Iterable<T>) self, closure);
}
/**
* Iterates through an SortedSet, passing each item to the given closure.
*
* @param self the SortedSet over which we iterate
* @param closure the closure applied on each element found
* @return the self SortedSet
* @since 2.4.0
*/
public static <T> SortedSet<T> each(SortedSet<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
return (SortedSet<T>) each((Iterable<T>) self, closure);
}
/**
* Allows a Map to be iterated through using a closure. If the
* closure takes one parameter then it will be passed the Map.Entry
* otherwise if the closure takes two parameters then it will be
* passed the key and the value.
* <pre class="groovyTestCase">def result = ""
* [a:1, b:3].each { key, value -> result += "$key$value" }
* assert result == "a1b3"</pre>
* <pre class="groovyTestCase">def result = ""
* [a:1, b:3].each { entry -> result += entry }
* assert result == "a=1b=3"</pre>
*
* In general, the order in which the map contents are processed
* cannot be guaranteed. In practise, specialized forms of Map,
* e.g. a TreeMap will have its contents processed according to
* the natural ordering of the map.
*
* @param self the map over which we iterate
* @param closure the 1 or 2 arg closure applied on each entry of the map
* @return returns the self parameter
* @since 1.5.0
*/
public static <K, V> Map<K, V> each(Map<K, V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure closure) {
for (Map.Entry entry : self.entrySet()) {
callClosureForMapEntry(closure, entry);
}
return self;
}
/**
* Allows a Map to be iterated through in reverse order using a closure.
*
* In general, the order in which the map contents are processed
* cannot be guaranteed. In practise, specialized forms of Map,
* e.g. a TreeMap will have its contents processed according to the
* reverse of the natural ordering of the map.
*
* @param self the map over which we iterate
* @param closure the 1 or 2 arg closure applied on each entry of the map
* @return returns the self parameter
* @see #each(Map, Closure)
* @since 1.7.2
*/
public static <K, V> Map<K, V> reverseEach(Map<K, V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure closure) {
final Iterator<Map.Entry<K, V>> entries = reverse(self.entrySet().iterator());
while (entries.hasNext()) {
callClosureForMapEntry(closure, entries.next());
}
return self;
}
/**
* Allows a Map to be iterated through using a closure. If the
* closure takes two parameters then it will be passed the Map.Entry and
* the item's index (a counter starting at zero) otherwise if the closure
* takes three parameters then it will be passed the key, the value, and
* the index.
* <pre class="groovyTestCase">def result = ""
* [a:1, b:3].eachWithIndex { key, value, index -> result += "$index($key$value)" }
* assert result == "0(a1)1(b3)"</pre>
* <pre class="groovyTestCase">def result = ""
* [a:1, b:3].eachWithIndex { entry, index -> result += "$index($entry)" }
* assert result == "0(a=1)1(b=3)"</pre>
*
* @param self the map over which we iterate
* @param closure a 2 or 3 arg Closure to operate on each item
* @return the self Object
* @since 1.5.0
*/
public static <K, V> Map<K, V> eachWithIndex(Map<K, V> self, @ClosureParams(value=MapEntryOrKeyValue.class, options="index=true") Closure closure) {
int counter = 0;
for (Map.Entry entry : self.entrySet()) {
callClosureForMapEntryAndCounter(closure, entry, counter++);
}
return self;
}
/**
* Iterate over each element of the list in the reverse order.
* <pre class="groovyTestCase">def result = []
* [1,2,3].reverseEach { result &lt;&lt; it }
* assert result == [3,2,1]</pre>
*
* @param self a List
* @param closure a closure to which each item is passed.
* @return the original list
* @since 1.5.0
*/
public static <T> List<T> reverseEach(List<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
each(new ReverseListIterator<T>(self), closure);
return self;
}
/**
* Iterate over each element of the array in the reverse order.
*
* @param self an array
* @param closure a closure to which each item is passed
* @return the original array
* @since 1.5.2
*/
public static <T> T[] reverseEach(T[] self, @ClosureParams(FirstParam.Component.class) Closure closure) {
each(new ReverseListIterator<T>(Arrays.asList(self)), closure);
return self;
}
/**
* Used to determine if the given predicate closure is valid (i.e.&nsbp;returns
* <code>true</code> for all items in this data structure).
* A simple example for a list:
* <pre>def list = [3,4,5]
* def greaterThanTwo = list.every { it > 2 }
* </pre>
*
* @param self the object over which we iterate
* @param closure 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;
}
/**
* Used to determine if the given predicate closure is valid (i.e.&nsbp;returns
* <code>true</code> for all items in this iterator).
* A simple example for a list:
* <pre>def list = [3,4,5]
* def greaterThanTwo = list.iterator().every { it > 2 }
* </pre>
*
* @param self the iterator over which we iterate
* @param closure 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);
while (self.hasNext()) {
if (!bcw.call(self.next())) {
return false;
}
}
return true;
}
/**
* Used to determine if the given predicate closure is valid (i.e.&nsbp;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
* @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);
}
/**
* Iterates over the entries of a map, and checks whether a predicate is
* valid for all entries. If the
* closure takes one parameter then it will be passed the Map.Entry
* otherwise if the closure takes two parameters then it will be
* passed the key and the value.
* <pre class="groovyTestCase">def map = [a:1, b:2.0, c:2L]
* 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
* @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);
for (Map.Entry<K, V> entry : self.entrySet()) {
if (!bcw.callForMap(entry)) {
return false;
}
}
return true;
}
/**
* Iterates over every element of a collection, and checks whether all
* elements are <code>true</code> according to the Groovy Truth.
* Equivalent to <code>self.every({element -> element})</code>
*
* @param self the object over which we iterate
* @return true if every item in the collection matches the closure
* predicate
* @since 1.5.0
*/
public static boolean every(Object self) {
BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker();
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
if (!bmi.convertToBoolean(iter.next())) {
return false;
}
}
return true;
}
/**
* Iterates over the contents of an object or collection, and checks whether a
* predicate is valid for at least one element.
*
* @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
* @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;
}
/**
* Iterates over the contents of an iterator, and checks whether a
* predicate is valid for at least one element.
*
* @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
* @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;
}
return false;
}
/**
* Iterates over the contents of an iterable, and checks whether a
* predicate is valid for at least one element.
*
* @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
* @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;
}
/**
* Iterates over the entries of a map, and checks whether a predicate is
* valid for at least one entry. If the
* closure takes one parameter then it will be passed the Map.Entry
* otherwise if the closure takes two parameters then it will be
* passed the key and the value.
* <pre class="groovyTestCase">
* assert [2:3, 4:5, 5:10].any { key, value -> key * 2 == value }
* 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
* @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);
for (Map.Entry<K, V> entry : self.entrySet()) {
if (bcw.callForMap(entry)) {
return true;
}
}
return false;
}
/**
* Iterates over the elements of a collection, and checks whether at least
* one element is true according to the Groovy Truth.
* Equivalent to self.any({element -> element})
*
* @param self the object over which we iterate
* @return true if any item in the collection matches the closure predicate
* @since 1.5.0
*/
public static boolean any(Object self) {
BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker();
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
if (bmi.convertToBoolean(iter.next())) {
return true;
}
}
return false;
}
/**
* Iterates over the collection of items which this Object represents and returns each item that matches
* the given filter - calling the <code>{@link #isCase(java.lang.Object, java.lang.Object)}</code>
* method used by switch statements. This method can be used with different
* kinds of filters like regular expressions, classes, ranges etc.
* Example:
* <pre class="groovyTestCase">
* def list = ['a', 'b', 'aa', 'bc', 3, 4.5]
* assert list.grep( ~/a+/ ) == ['a', 'aa']
* assert list.grep( ~/../ ) == ['aa', 'bc']
* assert list.grep( Number ) == [ 3, 4.5 ]
* assert list.grep{ it.toString().size() == 1 } == [ 'a', 'b', 3 ]
* </pre>
*
* @param self the object over which we iterate
* @param filter the filter to perform on the object (using the {@link #isCase(java.lang.Object, java.lang.Object)} method)
* @return a collection of objects which match the filter
* @since 1.5.6
*/
public static Collection grep(Object self, Object filter) {
Collection answer = createSimilarOrDefaultCollection(self);
BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker("isCase");
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
Object object = iter.next();
if (bmi.invoke(filter, object)) {
answer.add(object);
}
}
return answer;
}
/**
* Iterates over the collection of items and returns each item that matches
* the given filter - calling the <code>{@link #isCase(java.lang.Object, java.lang.Object)}</code>
* method used by switch statements. This method can be used with different
* kinds of filters like regular expressions, classes, ranges etc.
* Example:
* <pre class="groovyTestCase">
* def list = ['a', 'b', 'aa', 'bc', 3, 4.5]
* assert list.grep( ~/a+/ ) == ['a', 'aa']
* assert list.grep( ~/../ ) == ['aa', 'bc']
* assert list.grep( Number ) == [ 3, 4.5 ]
* assert list.grep{ it.toString().size() == 1 } == [ 'a', 'b', 3 ]
* </pre>
*
* @param self a collection
* @param filter the filter to perform on each element of the collection (using the {@link #isCase(java.lang.Object, java.lang.Object)} method)
* @return a collection of objects which match the filter
* @since 2.0
*/
public static <T> Collection<T> grep(Collection<T> self, Object filter) {
Collection<T> answer = createSimilarCollection(self);
BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker("isCase");
for (T element : self) {
if (bmi.invoke(filter, element)) {
answer.add(element);
}
}
return answer;
}
/**
* Iterates over the collection of items and returns each item that matches
* the given filter - calling the <code>{@link #isCase(java.lang.Object, java.lang.Object)}</code>
* method used by switch statements. This method can be used with different
* kinds of filters like regular expressions, classes, ranges etc.
* Example:
* <pre class="groovyTestCase">
* def list = ['a', 'b', 'aa', 'bc', 3, 4.5]
* assert list.grep( ~/a+/ ) == ['a', 'aa']
* assert list.grep( ~/../ ) == ['aa', 'bc']
* assert list.grep( Number ) == [ 3, 4.5 ]
* assert list.grep{ it.toString().size() == 1 } == [ 'a', 'b', 3 ]
* </pre>
*
* @param self a List
* @param filter the filter to perform on each element of the collection (using the {@link #isCase(java.lang.Object, java.lang.Object)} method)
* @return a List of objects which match the filter
* @since 2.4.0
*/
public static <T> List<T> grep(List<T> self, Object filter) {
return (List<T>) grep((Collection<T>) self, filter);
}
/**
* Iterates over the collection of items and returns each item that matches
* the given filter - calling the <code>{@link #isCase(java.lang.Object, java.lang.Object)}</code>
* method used by switch statements. This method can be used with different
* kinds of filters like regular expressions, classes, ranges etc.
* Example:
* <pre class="groovyTestCase">
* def set = ['a', 'b', 'aa', 'bc', 3, 4.5] as Set
* assert set.grep( ~/a+/ ) == ['a', 'aa'] as Set
* assert set.grep( ~/../ ) == ['aa', 'bc'] as Set
* assert set.grep( Number ) == [ 3, 4.5 ] as Set
* assert set.grep{ it.toString().size() == 1 } == [ 'a', 'b', 3 ] as Set
* </pre>
*
* @param self a Set
* @param filter the filter to perform on each element of the collection (using the {@link #isCase(java.lang.Object, java.lang.Object)} method)
* @return a Set of objects which match the filter
* @since 2.4.0
*/
public static <T> Set<T> grep(Set<T> self, Object filter) {
return (Set<T>) grep((Collection<T>) self, filter);
}
/**
* Iterates over the array of items and returns a collection of items that match
* the given filter - calling the <code>{@link #isCase(java.lang.Object, java.lang.Object)}</code>
* method used by switch statements. This method can be used with different
* kinds of filters like regular expressions, classes, ranges etc.
* Example:
* <pre class="groovyTestCase">
* def items = ['a', 'b', 'aa', 'bc', 3, 4.5] as Object[]
* assert items.grep( ~/a+/ ) == ['a', 'aa']
* assert items.grep( ~/../ ) == ['aa', 'bc']
* assert items.grep( Number ) == [ 3, 4.5 ]
* assert items.grep{ it.toString().size() == 1 } == [ 'a', 'b', 3 ]
* </pre>
*
* @param self an array
* @param filter the filter to perform on each element of the array (using the {@link #isCase(java.lang.Object, java.lang.Object)} method)
* @return a collection of objects which match the filter
* @since 2.0
*/
public static <T> Collection<T> grep(T[] self, Object filter) {
Collection<T> answer = new ArrayList<T>();
BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker("isCase");
for (T element : self) {
if (bmi.invoke(filter, element)) {
answer.add(element);
}
}
return answer;
}
/**
* Iterates over the collection of items which this Object represents and returns each item that matches
* using the IDENTITY Closure as a filter - effectively returning all elements which satisfy Groovy truth.
* <p>
* Example:
* <pre class="groovyTestCase">
* def items = [1, 2, 0, false, true, '', 'foo', [], [4, 5], null]
* assert items.grep() == [1, 2, true, 'foo', [4, 5]]
* </pre>
*
* @param self the object over which we iterate
* @return a collection of objects which match the filter
* @since 1.8.1
* @see Closure#IDENTITY
*/
public static Collection grep(Object self) {
return grep(self, Closure.IDENTITY);
}
/**
* Iterates over the collection returning each element that matches
* using the IDENTITY Closure as a filter - effectively returning all elements which satisfy Groovy truth.
* <p>
* Example:
* <pre class="groovyTestCase">
* def items = [1, 2, 0, false, true, '', 'foo', [], [4, 5], null]
* assert items.grep() == [1, 2, true, 'foo', [4, 5]]
* </pre>
*
* @param self a Collection
* @return a collection of elements satisfy Groovy truth
* @see Closure#IDENTITY
* @since 2.0
*/
public static <T> Collection<T> grep(Collection<T> self) {
return grep(self, Closure.IDENTITY);
}
/**
* Iterates over the collection returning each element that matches
* using the IDENTITY Closure as a filter - effectively returning all elements which satisfy Groovy truth.
* <p>
* Example:
* <pre class="groovyTestCase">
* def items = [1, 2, 0, false, true, '', 'foo', [], [4, 5], null]
* assert items.grep() == [1, 2, true, 'foo', [4, 5]]
* </pre>
*
* @param self a List
* @return a List of elements satisfy Groovy truth
* @see Closure#IDENTITY
* @since 2.4.0
*/
public static <T> List<T> grep(List<T> self) {
return grep(self, Closure.IDENTITY);
}
/**
* Iterates over the collection returning each element that matches
* using the IDENTITY Closure as a filter - effectively returning all elements which satisfy Groovy truth.
* <p>
* Example:
* <pre class="groovyTestCase">
* def items = [1, 2, 0, false, true, '', 'foo', [], [4, 5], null] as Set
* assert items.grep() == [1, 2, true, 'foo', [4, 5]] as Set
* </pre>
*
* @param self a Set
* @return a Set of elements satisfy Groovy truth
* @see Closure#IDENTITY
* @since 2.4.0
*/
public static <T> Set<T> grep(Set<T> self) {
return grep(self, Closure.IDENTITY);
}
/**
* Iterates over the array returning each element that matches
* using the IDENTITY Closure as a filter - effectively returning all elements which satisfy Groovy truth.
* <p>
* Example:
* <pre class="groovyTestCase">
* def items = [1, 2, 0, false, true, '', 'foo', [], [4, 5], null] as Object[]
* assert items.grep() == [1, 2, true, 'foo', [4, 5]]
* </pre>
*
* @param self an array
* @return a collection of elements which satisfy Groovy truth
* @see Closure#IDENTITY
* @since 2.0
*/
@SuppressWarnings("unchecked")
public static <T> Collection<T> grep(T[] self) {
return grep(self, Closure.IDENTITY);
}
/**
* Counts the number of occurrences of the given value from the
* items within this Iterator.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0</code> or <code>equals(value)</code> ).
* The iterator will become exhausted of elements after determining the count value.
*
* @param self the Iterator from which we count the number of matching occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.5.0
*/
public static Number count(Iterator self, Object value) {
long answer = 0;
while (self.hasNext()) {
if (DefaultTypeTransformation.compareEqual(self.next(), value)) {
++answer;
}
}
// for b/c with Java return an int if we can
if (answer <= Integer.MAX_VALUE) return (int) answer;
return answer;
}
/**
* Counts the number of occurrences which satisfy the given closure from the
* items within this Iterator.
* The iterator will become exhausted of elements after determining the count value.
* <p>
* Example usage:
* <pre class="groovyTestCase">assert [2,4,2,1,3,5,2,4,3].toSet().iterator().count{ it % 2 == 0 } == 2</pre>
*
* @param self the Iterator from which we count the number of matching occurrences
* @param closure a closure condition
* @return the number of occurrences
* @since 1.8.0
*/
public static <T> Number count(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
long answer = 0;
BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
while (self.hasNext()) {
if (bcw.call(self.next())) {
++answer;
}
}
// for b/c with Java return an int if we can
if (answer <= Integer.MAX_VALUE) return (int) answer;
return answer;
}
/**
* @deprecated use count(Iterable, Closure)
* @since 1.0
*/
@Deprecated
public static Number count(Collection self, Object value) {
return count(self.iterator(), value);
}
/**
* Counts the number of occurrences of the given value inside this Iterable.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0</code> or <code>equals(value)</code> ).
* <p>
* Example usage:
* <pre class="groovyTestCase">assert [2,4,2,1,3,5,2,4,3].count(4) == 2</pre>
*
* @param self the Iterable within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 2.2.0
*/
public static Number count(Iterable self, Object value) {
return count(self.iterator(), value);
}
/**
* @deprecated use count(Iterable, Closure)
* @since 1.8.0
*/
@Deprecated
public static Number count(Collection self, Closure closure) {
return count(self.iterator(), closure);
}
/**
* Counts the number of occurrences which satisfy the given closure from inside this Iterable.
* <p>
* Example usage:
* <pre class="groovyTestCase">assert [2,4,2,1,3,5,2,4,3].count{ it % 2 == 0 } == 5</pre>
*
* @param self the Iterable within which we count the number of occurrences
* @param closure a closure condition
* @return the number of occurrences
* @since 2.2.0
*/
public static <T> Number count(Iterable<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
return count(self.iterator(), closure);
}
/**
* Counts the number of occurrences which satisfy the given closure from inside this map.
* If the closure takes one parameter then it will be passed the Map.Entry.
* Otherwise, the closure should take two parameters and will be passed the key and value.
* <p>
* Example usage:
* <pre class="groovyTestCase">assert [a:1, b:1, c:2, d:2].count{ k,v -> k == 'a' || v == 2 } == 3</pre>
*
* @param self the map within which we count the number of occurrences
* @param closure a 1 or 2 arg Closure condition applying on the entries
* @return the number of occurrences
* @since 1.8.0
*/
public static <K,V> Number count(Map<K,V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure<?> closure) {
long answer = 0;
BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
for (Object entry : self.entrySet()) {
if (bcw.callForMap((Map.Entry)entry)) {
++answer;
}
}
// for b/c with Java return an int if we can
if (answer <= Integer.MAX_VALUE) return (int) answer;
return answer;
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0</code> or <code>equals(value)</code> ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(Object[] self, Object value) {
return count((Iterable)Arrays.asList(self), value);
}
/**
* Counts the number of occurrences which satisfy the given closure from inside this array.
*
* @param self the array within which we count the number of occurrences
* @param closure a closure condition
* @return the number of occurrences
* @since 1.8.0
*/
public static <T> Number count(T[] self, @ClosureParams(FirstParam.Component.class) Closure closure) {
return count((Iterable)Arrays.asList(self), closure);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0</code> or <code>equals(value)</code> ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(int[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0</code> or <code>equals(value)</code> ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(long[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0</code> or <code>equals(value)</code> ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(short[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0</code> or <code>equals(value)</code> ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(char[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0</code> or <code>equals(value)</code> ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(boolean[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0</code> or <code>equals(value)</code> ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(double[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0</code> or <code>equals(value)</code> ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(float[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0</code> or <code>equals(value)</code> ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(byte[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* @deprecated Use the Iterable version of toList instead
* @see #toList(Iterable)
* @since 1.0
*/
@Deprecated
public static <T> List<T> toList(Collection<T> self) {
List<T> answer = new ArrayList<T>(self.size());
answer.addAll(self);
return answer;
}
/**
* Convert an iterator to a List. The iterator will become
* exhausted of elements after making this conversion.
*
* @param self an iterator
* @return a List
* @since 1.5.0
*/
public static <T> List<T> toList(Iterator<T> self) {
List<T> answer = new ArrayList<T>();
while (self.hasNext()) {
answer.add(self.next());
}
return answer;
}
/**
* Convert an Iterable to a List. The Iterable's iterator will
* become exhausted of elements after making this conversion.
* <p>
* Example usage:
* <pre class="groovyTestCase">def x = [1,2,3] as HashSet
* assert x.class == HashSet
* assert x.toList() instanceof List</pre>
*
* @param self an Iterable
* @return a List
* @since 1.8.7
*/
public static <T> List<T> toList(Iterable<T> self) {
return toList(self.iterator());
}
/**
* Convert an enumeration to a List.
*
* @param self an enumeration
* @return a List
* @since 1.5.0
*/
public static <T> List<T> toList(Enumeration<T> self) {
List<T> answer = new ArrayList<T>();
while (self.hasMoreElements()) {
answer.add(self.nextElement());
}
return answer;
}
/**
* Collates this iterable into sub-lists of length <code>size</code>.
* Example:
* <pre class="groovyTestCase">def list = [ 1, 2, 3, 4, 5, 6, 7 ]
* def coll = list.collate( 3 )
* assert coll == [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7 ] ]</pre>
*
* @param self an Iterable
* @param size the length of each sub-list in the returned list
* @return a List containing the data collated into sub-lists
* @since 2.4.0
*/
public static <T> List<List<T>> collate(Iterable<T> self, int size) {
return collate(self, size, true);
}
/**
* @deprecated use the Iterable variant instead
* @see #collate(Iterable, int)
* @since 1.8.6
*/
@Deprecated
public static <T> List<List<T>> collate( List<T> self, int size ) {
return collate((Iterable<T>) self, size) ;
}
/**
* Collates this iterable into sub-lists of length <code>size</code> stepping through the code <code>step</code>
* elements for each subList.
* Example:
* <pre class="groovyTestCase">def list = [ 1, 2, 3, 4 ]
* def coll = list.collate( 3, 1 )
* assert coll == [ [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4 ], [ 4 ] ]</pre>
*
* @param self an Iterable
* @param size the length of each sub-list in the returned list
* @param step the number of elements to step through for each sub-list
* @return a List containing the data collated into sub-lists
* @since 2.4.0
*/
public static <T> List<List<T>> collate(Iterable<T> self, int size, int step) {
return collate(self, size, step, true);
}
/**
* @deprecated use the Iterable variant instead
* @see #collate(Iterable, int, int)
* @since 1.8.6
*/
@Deprecated
public static <T> List<List<T>> collate( List<T> self, int size, int step ) {
return collate((Iterable<T>) self, size, step) ;
}
/**
* Collates this iterable into sub-lists of length <code>size</code>. Any remaining elements in
* the iterable after the subdivision will be dropped if <code>keepRemainder</code> is false.
* Example:
* <pre class="groovyTestCase">def list = [ 1, 2, 3, 4, 5, 6, 7 ]
* def coll = list.collate( 3, false )
* assert coll == [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]</pre>
*
* @param self an Iterable
* @param size the length of each sub-list in the returned list
* @param keepRemainder if true, any remaining elements are returned as sub-lists. Otherwise they are discarded
* @return a List containing the data collated into sub-lists
* @since 2.4.0
*/
public static <T> List<List<T>> collate(Iterable<T> self, int size, boolean keepRemainder) {
return collate(self, size, size, keepRemainder);
}
/**
* @deprecated use the Iterable variant instead
* @see #collate(Iterable, int, boolean)
* @since 1.8.6
*/
@Deprecated
public static <T> List<List<T>> collate( List<T> self, int size, boolean keepRemainder ) {
return collate((Iterable<T>) self, size, keepRemainder) ;
}
/**
* Collates this iterable into sub-lists of length <code>size</code> stepping through the code <code>step</code>
* elements for each sub-list. Any remaining elements in the iterable after the subdivision will be dropped if
* <code>keepRemainder</code> is false.
* Example:
* <pre class="groovyTestCase">
* def list = [ 1, 2, 3, 4 ]
* assert list.collate( 2, 2, true ) == [ [ 1, 2 ], [ 3, 4 ] ]
* assert list.collate( 3, 1, true ) == [ [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4 ], [ 4 ] ]
* assert list.collate( 3, 1, false ) == [ [ 1, 2, 3 ], [ 2, 3, 4 ] ]
* </pre>
*
* @param self an Iterable
* @param size the length of each sub-list in the returned list
* @param step the number of elements to step through for each sub-list
* @param keepRemainder if true, any remaining elements are returned as sub-lists. Otherwise they are discarded
* @return a List containing the data collated into sub-lists
* @since 2.4.0
*/
public static <T> List<List<T>> collate(Iterable<T> self, int size, int step, boolean keepRemainder) {
List<T> selfList = asList(self);
List<List<T>> answer = new ArrayList<List<T>>();
if (size <= 0 || selfList.size() == 0) {
answer.add(selfList);
} else {
for (int pos = 0; pos < selfList.size() && pos > -1; pos += step) {
if (!keepRemainder && pos > selfList.size() - size) {
break ;
}
List<T> element = new ArrayList<T>() ;
for (int offs = pos; offs < pos + size && offs < selfList.size(); offs++) {
element.add(selfList.get(offs));
}
answer.add( element ) ;
}
}
return answer ;
}
/**
* @deprecated use the Iterable variant instead
* @see #collate(Iterable, int, int, boolean)
* @since 1.8.6
*/
@Deprecated
public static <T> List<List<T>> collate( List<T> self, int size, int step, boolean keepRemainder ) {
return collate((Iterable<T>) self, size, step, keepRemainder);
}
/**
* 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:
* <pre class="groovyTestCase">def list = [1, 'a', 1.23, true ]
* def types = list.collect { it.class }
* assert types == [Integer, String, BigDecimal, Boolean]</pre>
*
* @param self an aggregate Object with an Iterator returning its items
* @param transform the closure used to transform each item of the aggregate object
* @return a List of the transformed values
* @since 1.0
*/
public static <T> List<T> collect(Object self, Closure<T> transform) {
return (List<T>) collect(self, new ArrayList<T>(), transform);
}
/**
* 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 List 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
* and adding it to the supplied <code>collector</code>.
*
* @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) {
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext(); ) {
collector.add(transform.call(iter.next()));
}
return collector;
}
/**
* 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
* @since 1.0
*/
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 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
* @since 1.8.5
* @see Closure#IDENTITY
*/
public static <T> List<T> collect(Collection<T> self) {
return (List<T>) collect(self, Closure.IDENTITY);
}
/**
* 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
* @since 1.0
*/
public static <T,E> Collection<T> collect(Collection<E> self, Collection<T> collector, @ClosureParams(FirstParam