/* * Copyright 2015 Goldman Sachs. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.gs.collections.impl.utility; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import com.gs.collections.api.block.HashingStrategy; import com.gs.collections.api.block.function.Function; import com.gs.collections.api.block.function.Function0; import com.gs.collections.api.block.function.Function2; import com.gs.collections.api.block.function.Function3; import com.gs.collections.api.block.function.primitive.BooleanFunction; import com.gs.collections.api.block.function.primitive.ByteFunction; import com.gs.collections.api.block.function.primitive.CharFunction; import com.gs.collections.api.block.function.primitive.DoubleFunction; import com.gs.collections.api.block.function.primitive.DoubleObjectToDoubleFunction; import com.gs.collections.api.block.function.primitive.FloatFunction; import com.gs.collections.api.block.function.primitive.FloatObjectToFloatFunction; import com.gs.collections.api.block.function.primitive.IntFunction; import com.gs.collections.api.block.function.primitive.IntObjectToIntFunction; import com.gs.collections.api.block.function.primitive.LongFunction; import com.gs.collections.api.block.function.primitive.LongObjectToLongFunction; import com.gs.collections.api.block.function.primitive.ShortFunction; import com.gs.collections.api.block.predicate.Predicate; import com.gs.collections.api.block.predicate.Predicate2; import com.gs.collections.api.block.procedure.Procedure; import com.gs.collections.api.block.procedure.Procedure2; import com.gs.collections.api.block.procedure.primitive.ObjectIntProcedure; import com.gs.collections.api.collection.primitive.MutableBooleanCollection; import com.gs.collections.api.collection.primitive.MutableByteCollection; import com.gs.collections.api.collection.primitive.MutableCharCollection; import com.gs.collections.api.collection.primitive.MutableDoubleCollection; import com.gs.collections.api.collection.primitive.MutableFloatCollection; import com.gs.collections.api.collection.primitive.MutableIntCollection; import com.gs.collections.api.collection.primitive.MutableLongCollection; import com.gs.collections.api.collection.primitive.MutableShortCollection; import com.gs.collections.api.list.MutableList; import com.gs.collections.api.list.primitive.MutableBooleanList; import com.gs.collections.api.list.primitive.MutableByteList; import com.gs.collections.api.list.primitive.MutableCharList; import com.gs.collections.api.list.primitive.MutableDoubleList; import com.gs.collections.api.list.primitive.MutableFloatList; import com.gs.collections.api.list.primitive.MutableIntList; import com.gs.collections.api.list.primitive.MutableLongList; import com.gs.collections.api.list.primitive.MutableShortList; import com.gs.collections.api.map.MutableMap; import com.gs.collections.api.multimap.MutableMultimap; import com.gs.collections.api.partition.list.PartitionMutableList; import com.gs.collections.api.set.MutableSet; import com.gs.collections.api.tuple.Pair; import com.gs.collections.api.tuple.Twin; import com.gs.collections.impl.block.factory.Comparators; import com.gs.collections.impl.block.procedure.MutatingAggregationProcedure; import com.gs.collections.impl.block.procedure.NonMutatingAggregationProcedure; import com.gs.collections.impl.factory.Lists; import com.gs.collections.impl.list.mutable.FastList; import com.gs.collections.impl.list.mutable.primitive.BooleanArrayList; import com.gs.collections.impl.list.mutable.primitive.ByteArrayList; import com.gs.collections.impl.list.mutable.primitive.CharArrayList; import com.gs.collections.impl.list.mutable.primitive.DoubleArrayList; import com.gs.collections.impl.list.mutable.primitive.FloatArrayList; import com.gs.collections.impl.list.mutable.primitive.IntArrayList; import com.gs.collections.impl.list.mutable.primitive.LongArrayList; import com.gs.collections.impl.list.mutable.primitive.ShortArrayList; import com.gs.collections.impl.map.mutable.UnifiedMap; import com.gs.collections.impl.multimap.list.FastListMultimap; import com.gs.collections.impl.partition.list.PartitionFastList; import com.gs.collections.impl.set.mutable.UnifiedSet; import com.gs.collections.impl.set.strategy.mutable.UnifiedSetWithHashingStrategy; import com.gs.collections.impl.tuple.Tuples; import com.gs.collections.impl.utility.internal.InternalArrayIterate; import com.gs.collections.impl.utility.internal.RandomAccessListIterate; /** * This utility class provides optimized iteration pattern implementations that work with java.util.ArrayList. */ public final class ArrayListIterate { private static final Field ELEMENT_DATA_FIELD; private static final Field SIZE_FIELD; private static final int MIN_DIRECT_ARRAY_ACCESS_SIZE = 100; static { Field data = null; Field size = null; try { data = ArrayList.class.getDeclaredField("elementData"); size = ArrayList.class.getDeclaredField("size"); try { data.setAccessible(true); size.setAccessible(true); } catch (SecurityException ignored) { data = null; size = null; } } catch (NoSuchFieldException ignored) { } ELEMENT_DATA_FIELD = data; SIZE_FIELD = size; } private ArrayListIterate() { throw new AssertionError("Suppress default constructor for noninstantiability"); } /** * @see Iterate#select(Iterable, Predicate) */ public static <T> ArrayList<T> select(ArrayList<T> list, Predicate<? super T> predicate) { return ArrayListIterate.select(list, predicate, new ArrayList<T>()); } /** * @see Iterate#selectWith(Iterable, Predicate2, Object) */ public static <T, IV> ArrayList<T> selectWith( ArrayList<T> list, Predicate2<? super T, ? super IV> predicate, IV injectedValue) { return ArrayListIterate.selectWith(list, predicate, injectedValue, new ArrayList<T>()); } /** * @see Iterate#select(Iterable, Predicate, Collection) */ public static <T, R extends Collection<T>> R select( ArrayList<T> list, Predicate<? super T> predicate, R targetCollection) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (predicate.accept(elements[i])) { targetCollection.add(elements[i]); } } return targetCollection; } return RandomAccessListIterate.select(list, predicate, targetCollection); } /** * @see Iterate#selectWith(Iterable, Predicate2, Object, Collection) */ public static <T, P, R extends Collection<T>> R selectWith( ArrayList<T> list, Predicate2<? super T, ? super P> predicate, P parameter, R targetCollection) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (predicate.accept(elements[i], parameter)) { targetCollection.add(elements[i]); } } return targetCollection; } return RandomAccessListIterate.selectWith(list, predicate, parameter, targetCollection); } /** * @see Iterate#selectInstancesOf(Iterable, Class) */ public static <T> MutableList<T> selectInstancesOf( ArrayList<?> list, Class<T> clazz) { int size = list.size(); FastList<T> result = FastList.newList(size); if (ArrayListIterate.isOptimizableArrayList(list, size)) { Object[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { Object element = elements[i]; if (clazz.isInstance(element)) { result.add((T) element); } } result.trimToSize(); return result; } return RandomAccessListIterate.selectInstancesOf(list, clazz); } /** * @see Iterate#count(Iterable, Predicate) */ public static <T> int count(ArrayList<T> list, Predicate<? super T> predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { int count = 0; T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (predicate.accept(elements[i])) { count++; } } return count; } return RandomAccessListIterate.count(list, predicate); } /** * @see Iterate#countWith(Iterable, Predicate2, Object) */ public static <T, P> int countWith( ArrayList<T> list, Predicate2<? super T, ? super P> predicate, P parameter) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { int count = 0; T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (predicate.accept(elements[i], parameter)) { count++; } } return count; } return RandomAccessListIterate.countWith(list, predicate, parameter); } /** * @see Iterate#collectIf(Iterable, Predicate, Function) */ public static <T, A> ArrayList<A> collectIf( ArrayList<T> list, Predicate<? super T> predicate, Function<? super T, ? extends A> function) { return ArrayListIterate.collectIf(list, predicate, function, new ArrayList<A>()); } /** * @see Iterate#collectIf(Iterable, Predicate, Function, Collection) */ public static <T, A, R extends Collection<A>> R collectIf( ArrayList<T> list, Predicate<? super T> predicate, Function<? super T, ? extends A> function, R targetCollection) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (predicate.accept(elements[i])) { targetCollection.add(function.valueOf(elements[i])); } } return targetCollection; } return RandomAccessListIterate.collectIf(list, predicate, function, targetCollection); } /** * @see Iterate#reject(Iterable, Predicate) */ public static <T> ArrayList<T> reject(ArrayList<T> list, Predicate<? super T> predicate) { return ArrayListIterate.reject(list, predicate, new ArrayList<T>()); } /** * @see Iterate#rejectWith(Iterable, Predicate2, Object) */ public static <T, IV> ArrayList<T> rejectWith( ArrayList<T> list, Predicate2<? super T, ? super IV> predicate, IV injectedValue) { return ArrayListIterate.rejectWith(list, predicate, injectedValue, new ArrayList<T>()); } /** * @see Iterate#reject(Iterable, Predicate, Collection) */ public static <T, R extends Collection<T>> R reject( ArrayList<T> list, Predicate<? super T> predicate, R targetCollection) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (!predicate.accept(elements[i])) { targetCollection.add(elements[i]); } } return targetCollection; } return RandomAccessListIterate.reject(list, predicate, targetCollection); } /** * @see Iterate#reject(Iterable, Predicate, Collection) */ public static <T, P, R extends Collection<T>> R rejectWith( ArrayList<T> list, Predicate2<? super T, ? super P> predicate, P injectedValue, R targetCollection) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (!predicate.accept(elements[i], injectedValue)) { targetCollection.add(elements[i]); } } return targetCollection; } return RandomAccessListIterate.rejectWith(list, predicate, injectedValue, targetCollection); } /** * @see Iterate#collect(Iterable, Function) */ public static <T, A> ArrayList<A> collect( ArrayList<T> list, Function<? super T, ? extends A> function) { return ArrayListIterate.collect(list, function, new ArrayList<A>(list.size())); } /** * @see Iterate#collectBoolean(Iterable, BooleanFunction) */ public static <T> MutableBooleanList collectBoolean( ArrayList<T> list, BooleanFunction<? super T> booleanFunction) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableBooleanList result = new BooleanArrayList(size); return ArrayListIterate.collectBooleanFromInternalArray(list, booleanFunction, size, result); } return RandomAccessListIterate.collectBoolean(list, booleanFunction); } /** * @see Iterate#collectBoolean(Iterable, BooleanFunction, MutableBooleanCollection) */ public static <T, R extends MutableBooleanCollection> R collectBoolean(ArrayList<T> list, BooleanFunction<? super T> booleanFunction, R target) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { return ArrayListIterate.collectBooleanFromInternalArray(list, booleanFunction, size, target); } return RandomAccessListIterate.collectBoolean(list, booleanFunction, target); } private static <T, R extends MutableBooleanCollection> R collectBooleanFromInternalArray(ArrayList<T> source, BooleanFunction<? super T> booleanFunction, int elementsToCollect, R target) { T[] elements = ArrayListIterate.getInternalArray(source); for (int i = 0; i < elementsToCollect; i++) { target.add(booleanFunction.booleanValueOf(elements[i])); } return target; } /** * @see Iterate#collectByte(Iterable, ByteFunction) */ public static <T> MutableByteList collectByte( ArrayList<T> list, ByteFunction<? super T> byteFunction) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableByteList result = new ByteArrayList(size); return ArrayListIterate.collectByteFromInternalArray(list, byteFunction, size, result); } return RandomAccessListIterate.collectByte(list, byteFunction); } /** * @see Iterate#collectByte(Iterable, ByteFunction, MutableByteCollection) */ public static <T, R extends MutableByteCollection> R collectByte(ArrayList<T> list, ByteFunction<? super T> byteFunction, R target) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { return ArrayListIterate.collectByteFromInternalArray(list, byteFunction, size, target); } return RandomAccessListIterate.collectByte(list, byteFunction, target); } private static <T, R extends MutableByteCollection> R collectByteFromInternalArray(ArrayList<T> source, ByteFunction<? super T> byteFunction, int elementsToCollect, R target) { T[] elements = ArrayListIterate.getInternalArray(source); for (int i = 0; i < elementsToCollect; i++) { target.add(byteFunction.byteValueOf(elements[i])); } return target; } /** * @see Iterate#collectChar(Iterable, CharFunction) */ public static <T> MutableCharList collectChar( ArrayList<T> list, CharFunction<? super T> charFunction) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableCharList result = new CharArrayList(size); return ArrayListIterate.collectCharFromInternalArray(list, charFunction, size, result); } return RandomAccessListIterate.collectChar(list, charFunction); } /** * @see Iterate#collectChar(Iterable, CharFunction, MutableCharCollection) */ public static <T, R extends MutableCharCollection> R collectChar(ArrayList<T> list, CharFunction<? super T> charFunction, R target) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { return ArrayListIterate.collectCharFromInternalArray(list, charFunction, size, target); } return RandomAccessListIterate.collectChar(list, charFunction, target); } private static <T, R extends MutableCharCollection> R collectCharFromInternalArray(ArrayList<T> source, CharFunction<? super T> charFunction, int elementsToCollect, R target) { T[] elements = ArrayListIterate.getInternalArray(source); for (int i = 0; i < elementsToCollect; i++) { target.add(charFunction.charValueOf(elements[i])); } return target; } /** * @see Iterate#collectDouble(Iterable, DoubleFunction) */ public static <T> MutableDoubleList collectDouble( ArrayList<T> list, DoubleFunction<? super T> doubleFunction) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableDoubleList result = new DoubleArrayList(size); return ArrayListIterate.collectDoubleFromInternalArray(list, doubleFunction, size, result); } return RandomAccessListIterate.collectDouble(list, doubleFunction); } /** * @see Iterate#collectDouble(Iterable, DoubleFunction, MutableDoubleCollection) */ public static <T, R extends MutableDoubleCollection> R collectDouble(ArrayList<T> list, DoubleFunction<? super T> doubleFunction, R target) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { return ArrayListIterate.collectDoubleFromInternalArray(list, doubleFunction, size, target); } return RandomAccessListIterate.collectDouble(list, doubleFunction, target); } private static <T, R extends MutableDoubleCollection> R collectDoubleFromInternalArray(ArrayList<T> source, DoubleFunction<? super T> doubleFunction, int elementsToCollect, R target) { T[] elements = ArrayListIterate.getInternalArray(source); for (int i = 0; i < elementsToCollect; i++) { target.add(doubleFunction.doubleValueOf(elements[i])); } return target; } /** * @see Iterate#collectFloat(Iterable, FloatFunction) */ public static <T> MutableFloatList collectFloat( ArrayList<T> list, FloatFunction<? super T> floatFunction) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableFloatList result = new FloatArrayList(size); return ArrayListIterate.collectFloatFromInternalArray(list, floatFunction, size, result); } return RandomAccessListIterate.collectFloat(list, floatFunction); } /** * @see Iterate#collectFloat(Iterable, FloatFunction, MutableFloatCollection) */ public static <T, R extends MutableFloatCollection> R collectFloat(ArrayList<T> list, FloatFunction<? super T> floatFunction, R target) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { return ArrayListIterate.collectFloatFromInternalArray(list, floatFunction, size, target); } return RandomAccessListIterate.collectFloat(list, floatFunction, target); } private static <T, R extends MutableFloatCollection> R collectFloatFromInternalArray(ArrayList<T> source, FloatFunction<? super T> floatFunction, int elementsToCollect, R target) { T[] elements = ArrayListIterate.getInternalArray(source); for (int i = 0; i < elementsToCollect; i++) { target.add(floatFunction.floatValueOf(elements[i])); } return target; } /** * @see Iterate#collectInt(Iterable, IntFunction) */ public static <T> MutableIntList collectInt( ArrayList<T> list, IntFunction<? super T> intFunction) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableIntList result = new IntArrayList(size); return ArrayListIterate.collectIntFromInternalArray(list, intFunction, size, result); } return RandomAccessListIterate.collectInt(list, intFunction); } /** * @see Iterate#collectInt(Iterable, IntFunction, MutableIntCollection) */ public static <T, R extends MutableIntCollection> R collectInt(ArrayList<T> list, IntFunction<? super T> intFunction, R target) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { return ArrayListIterate.collectIntFromInternalArray(list, intFunction, size, target); } return RandomAccessListIterate.collectInt(list, intFunction, target); } private static <T, R extends MutableIntCollection> R collectIntFromInternalArray(ArrayList<T> source, IntFunction<? super T> intFunction, int elementsToCollect, R target) { T[] elements = ArrayListIterate.getInternalArray(source); for (int i = 0; i < elementsToCollect; i++) { target.add(intFunction.intValueOf(elements[i])); } return target; } /** * @see Iterate#collectLong(Iterable, LongFunction) */ public static <T> MutableLongList collectLong( ArrayList<T> list, LongFunction<? super T> longFunction) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableLongList result = new LongArrayList(size); return ArrayListIterate.collectLongFromInternalArray(list, longFunction, size, result); } return RandomAccessListIterate.collectLong(list, longFunction); } /** * @see Iterate#collectLong(Iterable, LongFunction, MutableLongCollection) */ public static <T, R extends MutableLongCollection> R collectLong(ArrayList<T> list, LongFunction<? super T> longFunction, R target) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { return ArrayListIterate.collectLongFromInternalArray(list, longFunction, size, target); } return RandomAccessListIterate.collectLong(list, longFunction, target); } private static <T, R extends MutableLongCollection> R collectLongFromInternalArray(ArrayList<T> source, LongFunction<? super T> longFunction, int elementsToCollect, R target) { T[] elements = ArrayListIterate.getInternalArray(source); for (int i = 0; i < elementsToCollect; i++) { target.add(longFunction.longValueOf(elements[i])); } return target; } /** * @see Iterate#collectShort(Iterable, ShortFunction) */ public static <T> MutableShortList collectShort( ArrayList<T> list, ShortFunction<? super T> shortFunction) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableShortList result = new ShortArrayList(size); return ArrayListIterate.collectShortFromInternalArray(list, shortFunction, size, result); } return RandomAccessListIterate.collectShort(list, shortFunction); } /** * @see Iterate#collectShort(Iterable, ShortFunction, MutableShortCollection) */ public static <T, R extends MutableShortCollection> R collectShort(ArrayList<T> list, ShortFunction<? super T> shortFunction, R target) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { return ArrayListIterate.collectShortFromInternalArray(list, shortFunction, size, target); } return RandomAccessListIterate.collectShort(list, shortFunction, target); } private static <T, R extends MutableShortCollection> R collectShortFromInternalArray(ArrayList<T> source, ShortFunction<? super T> shortFunction, int elementsToCollect, R target) { T[] elements = ArrayListIterate.getInternalArray(source); for (int i = 0; i < elementsToCollect; i++) { target.add(shortFunction.shortValueOf(elements[i])); } return target; } /** * @see Iterate#collect(Iterable, Function, Collection) */ public static <T, A, R extends Collection<A>> R collect( ArrayList<T> list, Function<? super T, ? extends A> function, R targetCollection) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { targetCollection.add(function.valueOf(elements[i])); } return targetCollection; } return RandomAccessListIterate.collect(list, function, targetCollection); } /** * @see Iterate#flatCollect(Iterable, Function) */ public static <T, A> ArrayList<A> flatCollect( ArrayList<T> list, Function<? super T, ? extends Iterable<A>> function) { return ArrayListIterate.flatCollect(list, function, new ArrayList<A>(list.size())); } /** * @see Iterate#flatCollect(Iterable, Function, Collection) */ public static <T, A, R extends Collection<A>> R flatCollect( ArrayList<T> list, Function<? super T, ? extends Iterable<A>> function, R targetCollection) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { Iterate.addAllTo(function.valueOf(elements[i]), targetCollection); } return targetCollection; } return RandomAccessListIterate.flatCollect(list, function, targetCollection); } /** * @see Iterate#forEach(Iterable, Procedure) */ public static <T> void forEach(ArrayList<T> list, Procedure<? super T> procedure) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { procedure.value(elements[i]); } } else { RandomAccessListIterate.forEach(list, procedure); } } /** * Reverses over the List in reverse order executing the Procedure for each element */ public static <T> void reverseForEach(ArrayList<T> list, Procedure<? super T> procedure) { if (!list.isEmpty()) { ArrayListIterate.forEach(list, list.size() - 1, 0, procedure); } } /** * Iterates over the section of the list covered by the specified indexes. The indexes are both inclusive. If the * from is less than the to, the list is iterated in forward order. If the from is greater than the to, then the * list is iterated in the reverse order. * <p> * <pre>e.g. * ArrayList<People> people = new ArrayList<People>(FastList.newListWith(ted, mary, bob, sally)); * ArrayListIterate.forEach(people, 0, 1, new Procedure<Person>() * { * public void value(Person person) * { * LOGGER.info(person.getName()); * } * }); * </pre> * <p> * This code would output ted and mary's names. */ public static <T> void forEach(ArrayList<T> list, int from, int to, Procedure<? super T> procedure) { ListIterate.rangeCheck(from, to, list.size()); if (ArrayListIterate.isOptimizableArrayList(list, to - from + 1)) { T[] elements = ArrayListIterate.getInternalArray(list); InternalArrayIterate.forEachWithoutChecks(elements, from, to, procedure); } else { RandomAccessListIterate.forEach(list, from, to, procedure); } } /** * Iterates over the section of the list covered by the specified indexes. The indexes are both inclusive. If the * from is less than the to, the list is iterated in forward order. If the from is greater than the to, then the * list is iterated in the reverse order. The index passed into the ObjectIntProcedure is the actual index of the * range. * <p> * <pre>e.g. * ArrayList<People> people = new ArrayList<People>(FastList.newListWith(ted, mary, bob, sally)); * ArrayListIterate.forEachWithIndex(people, 0, 1, new ObjectIntProcedure<Person>() * { * public void value(Person person, int index) * { * LOGGER.info(person.getName() + " at index: " + index); * } * }); * </pre> * <p> * This code would output ted and mary's names. */ public static <T> void forEachWithIndex( ArrayList<T> list, int from, int to, ObjectIntProcedure<? super T> objectIntProcedure) { ListIterate.rangeCheck(from, to, list.size()); if (ArrayListIterate.isOptimizableArrayList(list, to - from + 1)) { T[] elements = ArrayListIterate.getInternalArray(list); InternalArrayIterate.forEachWithIndexWithoutChecks(elements, from, to, objectIntProcedure); } else { RandomAccessListIterate.forEachWithIndex(list, from, to, objectIntProcedure); } } /** * @see ListIterate#forEachInBoth(List, List, Procedure2) */ public static <T1, T2> void forEachInBoth( ArrayList<T1> list1, ArrayList<T2> list2, Procedure2<? super T1, ? super T2> procedure) { RandomAccessListIterate.forEachInBoth(list1, list2, procedure); } /** * @see Iterate#forEachWithIndex(Iterable, ObjectIntProcedure) */ public static <T> void forEachWithIndex(ArrayList<T> list, ObjectIntProcedure<? super T> objectIntProcedure) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { objectIntProcedure.value(elements[i], i); } } else { RandomAccessListIterate.forEachWithIndex(list, objectIntProcedure); } } /** * @see Iterate#detect(Iterable, Predicate) */ public static <T> T detect(ArrayList<T> list, Predicate<? super T> predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { T item = elements[i]; if (predicate.accept(item)) { return item; } } return null; } return RandomAccessListIterate.detect(list, predicate); } /** * @see Iterate#detectWith(Iterable, Predicate2, Object) */ public static <T, P> T detectWith( ArrayList<T> list, Predicate2<? super T, ? super P> predicate, P parameter) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { T item = elements[i]; if (predicate.accept(item, parameter)) { return item; } } return null; } return RandomAccessListIterate.detectWith(list, predicate, parameter); } /** * @see Iterate#detectIfNone(Iterable, Predicate, Object) */ public static <T> T detectIfNone(ArrayList<T> list, Predicate<? super T> predicate, T ifNone) { T result = ArrayListIterate.detect(list, predicate); return result == null ? ifNone : result; } /** * @see Iterate#detectWithIfNone(Iterable, Predicate2, Object, Object) */ public static <T, IV> T detectWithIfNone( ArrayList<T> list, Predicate2<? super T, ? super IV> predicate, IV injectedValue, T ifNone) { T result = ArrayListIterate.detectWith(list, predicate, injectedValue); return result == null ? ifNone : result; } /** * @see Iterate#injectInto(Object, Iterable, Function2) */ public static <T, IV> IV injectInto( IV injectValue, ArrayList<T> list, Function2<? super IV, ? super T, ? extends IV> function) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { IV result = injectValue; T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { result = function.value(result, elements[i]); } return result; } return RandomAccessListIterate.injectInto(injectValue, list, function); } /** * @see Iterate#injectInto(int, Iterable, IntObjectToIntFunction) */ public static <T> int injectInto( int injectValue, ArrayList<T> list, IntObjectToIntFunction<? super T> function) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { int result = injectValue; T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { result = function.intValueOf(result, elements[i]); } return result; } return RandomAccessListIterate.injectInto(injectValue, list, function); } /** * @see Iterate#injectInto(long, Iterable, LongObjectToLongFunction) */ public static <T> long injectInto( long injectValue, ArrayList<T> list, LongObjectToLongFunction<? super T> function) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { long result = injectValue; T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { result = function.longValueOf(result, elements[i]); } return result; } return RandomAccessListIterate.injectInto(injectValue, list, function); } /** * @see Iterate#injectInto(double, Iterable, DoubleObjectToDoubleFunction) */ public static <T> double injectInto( double injectValue, ArrayList<T> list, DoubleObjectToDoubleFunction<? super T> function) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { double result = injectValue; T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { result = function.doubleValueOf(result, elements[i]); } return result; } return RandomAccessListIterate.injectInto(injectValue, list, function); } /** * @see Iterate#injectInto(float, Iterable, FloatObjectToFloatFunction) */ public static <T> float injectInto( float injectValue, ArrayList<T> list, FloatObjectToFloatFunction<? super T> function) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { float result = injectValue; T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { result = function.floatValueOf(result, elements[i]); } return result; } return RandomAccessListIterate.injectInto(injectValue, list, function); } /** * @see Iterate#anySatisfy(Iterable, Predicate) */ public static <T> boolean anySatisfy(ArrayList<T> list, Predicate<? super T> predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (predicate.accept(elements[i])) { return true; } } return false; } return RandomAccessListIterate.anySatisfy(list, predicate); } /** * @see Iterate#anySatisfyWith(Iterable, Predicate2, Object) */ public static <T, P> boolean anySatisfyWith( ArrayList<T> list, Predicate2<? super T, ? super P> predicate, P parameter) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (predicate.accept(elements[i], parameter)) { return true; } } return false; } return RandomAccessListIterate.anySatisfyWith(list, predicate, parameter); } /** * @see Iterate#allSatisfy(Iterable, Predicate) */ public static <T> boolean allSatisfy(ArrayList<T> list, Predicate<? super T> predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (!predicate.accept(elements[i])) { return false; } } return true; } return RandomAccessListIterate.allSatisfy(list, predicate); } /** * @see Iterate#allSatisfyWith(Iterable, Predicate2, Object) */ public static <T, IV> boolean allSatisfyWith( ArrayList<T> list, Predicate2<? super T, ? super IV> predicate, IV injectedValue) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (!predicate.accept(elements[i], injectedValue)) { return false; } } return true; } return RandomAccessListIterate.allSatisfyWith(list, predicate, injectedValue); } /** * @see Iterate#noneSatisfy(Iterable, Predicate) */ public static <T> boolean noneSatisfy(ArrayList<T> list, Predicate<? super T> predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (predicate.accept(elements[i])) { return false; } } return true; } return RandomAccessListIterate.noneSatisfy(list, predicate); } /** * @see Iterate#noneSatisfyWith(Iterable, Predicate2, Object) */ public static <T, IV> boolean noneSatisfyWith( ArrayList<T> list, Predicate2<? super T, ? super IV> predicate, IV injectedValue) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (predicate.accept(elements[i], injectedValue)) { return false; } } return true; } return RandomAccessListIterate.noneSatisfyWith(list, predicate, injectedValue); } /** * @see Iterate#selectAndRejectWith(Iterable, Predicate2, Object) */ public static <T, P> Twin<MutableList<T>> selectAndRejectWith( ArrayList<T> list, Predicate2<? super T, ? super P> predicate, P parameter) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableList<T> positiveResult = Lists.mutable.empty(); MutableList<T> negativeResult = Lists.mutable.empty(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { (predicate.accept(elements[i], parameter) ? positiveResult : negativeResult).add(elements[i]); } return Tuples.twin(positiveResult, negativeResult); } return RandomAccessListIterate.selectAndRejectWith(list, predicate, parameter); } /** * @see Iterate#partition(Iterable, Predicate) */ public static <T> PartitionMutableList<T> partition(ArrayList<T> list, Predicate<? super T> predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { PartitionFastList<T> partitionFastList = new PartitionFastList<T>(); MutableList<T> selected = partitionFastList.getSelected(); MutableList<T> rejected = partitionFastList.getRejected(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { T each = elements[i]; MutableList<T> bucket = predicate.accept(each) ? selected : rejected; bucket.add(each); } return partitionFastList; } return RandomAccessListIterate.partition(list, predicate); } public static <T, P> PartitionMutableList<T> partitionWith(ArrayList<T> list, Predicate2<? super T, ? super P> predicate, P parameter) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { PartitionFastList<T> partitionFastList = new PartitionFastList<T>(); MutableList<T> selected = partitionFastList.getSelected(); MutableList<T> rejected = partitionFastList.getRejected(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { T each = elements[i]; MutableList<T> bucket = predicate.accept(each, parameter) ? selected : rejected; bucket.add(each); } return partitionFastList; } return RandomAccessListIterate.partitionWith(list, predicate, parameter); } /** * @see Iterate#detectIndex(Iterable, Predicate) */ public static <T> int detectIndex(ArrayList<T> list, Predicate<? super T> predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (predicate.accept(elements[i])) { return i; } } return -1; } return RandomAccessListIterate.detectIndex(list, predicate); } /** * @see Iterate#detectIndexWith(Iterable, Predicate2, Object) */ public static <T, P> int detectIndexWith( ArrayList<T> list, Predicate2<? super T, ? super P> predicate, P parameter) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (predicate.accept(elements[i], parameter)) { return i; } } return -1; } return RandomAccessListIterate.detectIndexWith(list, predicate, parameter); } /** * @see ListIterate#detectLastIndex(List, Predicate) */ public static <T> int detectLastIndex(ArrayList<T> list, Predicate<? super T> predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = size - 1; i >= 0; i--) { if (predicate.accept(elements[i])) { return i; } } return -1; } return RandomAccessListIterate.detectLastIndex(list, predicate); } /** * @see Iterate#injectIntoWith(Object, Iterable, Function3, Object) */ public static <T, IV, P> IV injectIntoWith( IV injectedValue, ArrayList<T> list, Function3<? super IV, ? super T, ? super P, ? extends IV> function, P parameter) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { IV result = injectedValue; T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { result = function.value(result, elements[i], parameter); } return result; } return RandomAccessListIterate.injectIntoWith(injectedValue, list, function, parameter); } /** * @see Iterate#forEachWith(Iterable, Procedure2, Object) */ public static <T, P> void forEachWith( ArrayList<T> list, Procedure2<? super T, ? super P> procedure, P parameter) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { procedure.value(elements[i], parameter); } } else { RandomAccessListIterate.forEachWith(list, procedure, parameter); } } /** * @see Iterate#collectWith(Iterable, Function2, Object) */ public static <T, P, A> ArrayList<A> collectWith( ArrayList<T> list, Function2<? super T, ? super P, ? extends A> function, P parameter) { return ArrayListIterate.collectWith(list, function, parameter, new ArrayList<A>(list.size())); } /** * @see Iterate#collectWith(Iterable, Function2, Object, Collection) */ public static <T, P, A, R extends Collection<A>> R collectWith( ArrayList<T> list, Function2<? super T, ? super P, ? extends A> function, P parameter, R targetCollection) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { targetCollection.add(function.value(elements[i], parameter)); } return targetCollection; } return RandomAccessListIterate.collectWith(list, function, parameter, targetCollection); } /** * @see Iterate#removeIf(Iterable, Predicate) */ public static <T> boolean removeIf(ArrayList<T> list, Predicate<? super T> predicate) { boolean changed; if (list.getClass() == ArrayList.class && ArrayListIterate.SIZE_FIELD != null) { int currentFilledIndex = 0; int size = list.size(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (!predicate.accept(elements[i])) { // keep it if (currentFilledIndex != i) { elements[currentFilledIndex] = elements[i]; } currentFilledIndex++; } } changed = currentFilledIndex < size; ArrayListIterate.wipeAndResetTheEnd(currentFilledIndex, size, elements, list); } else { return RandomAccessListIterate.removeIf(list, predicate); } return changed; } /** * @see Iterate#removeIfWith(Iterable, Predicate2, Object) */ public static <T, P> boolean removeIfWith( ArrayList<T> list, Predicate2<? super T, ? super P> predicate, P parameter) { boolean changed; if (list.getClass() == ArrayList.class && ArrayListIterate.SIZE_FIELD != null) { int currentFilledIndex = 0; int size = list.size(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (!predicate.accept(elements[i], parameter)) { // keep it if (currentFilledIndex != i) { elements[currentFilledIndex] = elements[i]; } currentFilledIndex++; } } changed = currentFilledIndex < size; ArrayListIterate.wipeAndResetTheEnd(currentFilledIndex, size, elements, list); } else { return RandomAccessListIterate.removeIfWith(list, predicate, parameter); } return changed; } public static <T> ArrayList<T> distinct(ArrayList<T> list) { return ArrayListIterate.distinct(list, new ArrayList<T>()); } /** * @deprecated in 7.0. */ @Deprecated public static <T, R extends List<T>> R distinct(ArrayList<T> list, R targetList) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableSet<T> seenSoFar = UnifiedSet.newSet(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (seenSoFar.add(elements[i])) { targetList.add(elements[i]); } } return targetList; } return RandomAccessListIterate.distinct(list, targetList); } /** * @since 7.0. */ public static <T> ArrayList<T> distinct(ArrayList<T> list, HashingStrategy<? super T> hashingStrategy) { int size = list.size(); MutableSet<T> seenSoFar = UnifiedSetWithHashingStrategy.newSet(hashingStrategy); ArrayList<T> result = new ArrayList<T>(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (seenSoFar.add(elements[i])) { result.add(elements[i]); } } } else { for (int i = 0; i < size; i++) { T item = list.get(i); if (seenSoFar.add(item)) { result.add(item); } } } return result; } private static <T> void wipeAndResetTheEnd( int newCurrentFilledIndex, int newSize, T[] newElements, ArrayList<T> list) { for (int i = newCurrentFilledIndex; i < newSize; i++) { newElements[i] = null; } try { ArrayListIterate.SIZE_FIELD.setInt(list, newCurrentFilledIndex); } catch (IllegalAccessException e) { throw new RuntimeException( "Something really bad happened on the way to pounding size into the ArrayList reflectively", e); } } /** * Mutates the internal array of the ArrayList by sorting it and then returns the same ArrayList. */ public static <T extends Comparable<? super T>> ArrayList<T> sortThis(ArrayList<T> list) { return ArrayListIterate.sortThis(list, Comparators.naturalOrder()); } /** * Mutates the internal array of the ArrayList by sorting it and then returns the same ArrayList. */ public static <T> ArrayList<T> sortThis(ArrayList<T> list, Comparator<? super T> comparator) { int size = list.size(); if (ArrayListIterate.canAccessInternalArray(list)) { Arrays.sort(ArrayListIterate.getInternalArray(list), 0, size, comparator); } else { Collections.sort(list, comparator); } return list; } public static <T> void toArray(ArrayList<T> list, T[] target, int startIndex, int sourceSize) { if (ArrayListIterate.canAccessInternalArray(list)) { System.arraycopy(ArrayListIterate.getInternalArray(list), 0, target, startIndex, sourceSize); } else { RandomAccessListIterate.toArray(list, target, startIndex, sourceSize); } } /** * @see Iterate#take(Iterable, int) */ public static <T> ArrayList<T> take(ArrayList<T> list, int count) { if (count < 0) { throw new IllegalArgumentException("Count must be greater than zero, but was: " + count); } return ArrayListIterate.take(list, count, new ArrayList<T>(Math.min(list.size(), count))); } /** * @see Iterate#take(Iterable, int) */ public static <T, R extends Collection<T>> R take(ArrayList<T> list, int count, R targetList) { if (count < 0) { throw new IllegalArgumentException("Count must be greater than zero, but was: " + count); } int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); int end = Math.min(size, count); for (int i = 0; i < end; i++) { targetList.add(elements[i]); } return targetList; } return RandomAccessListIterate.take(list, count, targetList); } /** * @see Iterate#drop(Iterable, int) */ public static <T> ArrayList<T> drop(ArrayList<T> list, int count) { if (count < 0) { throw new IllegalArgumentException("Count must be greater than zero, but was: " + count); } return ArrayListIterate.drop(list, count, new ArrayList<T>(list.size() - Math.min(list.size(), count))); } /** * @see Iterate#drop(Iterable, int) */ public static <T, R extends Collection<T>> R drop(ArrayList<T> list, int count, R targetList) { if (count < 0) { throw new IllegalArgumentException("Count must be greater than zero, but was: " + count); } int size = list.size(); if (count >= size) { return targetList; } if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = count; i < size; i++) { targetList.add(elements[i]); } return targetList; } return RandomAccessListIterate.drop(list, count, targetList); } /** * @see Iterate#groupBy(Iterable, Function) */ public static <T, V> FastListMultimap<V, T> groupBy( ArrayList<T> list, Function<? super T, ? extends V> function) { return ArrayListIterate.groupBy(list, function, FastListMultimap.<V, T>newMultimap()); } /** * @see Iterate#groupBy(Iterable, Function, MutableMultimap) */ public static <T, V, R extends MutableMultimap<V, T>> R groupBy( ArrayList<T> list, Function<? super T, ? extends V> function, R target) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { target.put(function.valueOf(elements[i]), elements[i]); } return target; } return RandomAccessListIterate.groupBy(list, function, target); } /** * @see Iterate#groupByEach(Iterable, Function) */ public static <T, V> FastListMultimap<V, T> groupByEach( ArrayList<T> list, Function<? super T, ? extends Iterable<V>> function) { return ArrayListIterate.groupByEach(list, function, FastListMultimap.<V, T>newMultimap()); } /** * @see Iterate#groupByEach(Iterable, Function, MutableMultimap) */ public static <T, V, R extends MutableMultimap<V, T>> R groupByEach( ArrayList<T> list, Function<? super T, ? extends Iterable<V>> function, R target) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { Iterable<V> iterable = function.valueOf(elements[i]); for (V key : iterable) { target.put(key, elements[i]); } } return target; } return RandomAccessListIterate.groupByEach(list, function, target); } /** * @see Iterate#groupByUniqueKey(Iterable, Function) */ public static <T, V> MutableMap<V, T> groupByUniqueKey( ArrayList<T> list, Function<? super T, ? extends V> function) { return ArrayListIterate.groupByUniqueKey(list, function, UnifiedMap.<V, T>newMap()); } /** * @see Iterate#groupByUniqueKey(Iterable, Function, MutableMap) */ public static <T, V, R extends MutableMap<V, T>> R groupByUniqueKey( ArrayList<T> list, Function<? super T, ? extends V> function, R target) { if (list == null) { throw new IllegalArgumentException("Cannot perform a groupByUniqueKey on null"); } int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { V key = function.valueOf(elements[i]); if (target.put(key, elements[i]) != null) { throw new IllegalStateException("Key " + key + " already exists in map!"); } } return target; } return RandomAccessListIterate.groupByUniqueKey(list, function, target); } /** * @see Iterate#zip(Iterable, Iterable) */ public static <X, Y> MutableList<Pair<X, Y>> zip(ArrayList<X> xs, Iterable<Y> ys) { return ArrayListIterate.zip(xs, ys, FastList.<Pair<X, Y>>newList()); } /** * @see Iterate#zip(Iterable, Iterable, Collection) */ public static <X, Y, R extends Collection<Pair<X, Y>>> R zip(ArrayList<X> xs, Iterable<Y> ys, R targetCollection) { int size = xs.size(); if (ArrayListIterate.isOptimizableArrayList(xs, size)) { Iterator<Y> yIterator = ys.iterator(); X[] elements = ArrayListIterate.getInternalArray(xs); for (int i = 0; i < size && yIterator.hasNext(); i++) { targetCollection.add(Tuples.pair(elements[i], yIterator.next())); } return targetCollection; } return RandomAccessListIterate.zip(xs, ys, targetCollection); } /** * @see Iterate#zipWithIndex(Iterable) */ public static <T> MutableList<Pair<T, Integer>> zipWithIndex(ArrayList<T> list) { return ArrayListIterate.zipWithIndex(list, FastList.<Pair<T, Integer>>newList()); } /** * @see Iterate#zipWithIndex(Iterable, Collection) */ public static <T, R extends Collection<Pair<T, Integer>>> R zipWithIndex(ArrayList<T> list, R targetCollection) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { targetCollection.add(Tuples.pair(elements[i], i)); } return targetCollection; } return RandomAccessListIterate.zipWithIndex(list, targetCollection); } public static <T> MutableList<T> takeWhile(ArrayList<T> list, Predicate<? super T> predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableList<T> result = FastList.newList(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { T element = elements[i]; if (predicate.accept(element)) { result.add(element); } else { return result; } } return result; } return RandomAccessListIterate.takeWhile(list, predicate); } public static <T> MutableList<T> dropWhile(ArrayList<T> list, Predicate<? super T> predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableList<T> result = FastList.newList(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { T element = elements[i]; if (!predicate.accept(element)) { result.add(element); for (int j = i + 1; j < size; j++) { T eachNotDropped = elements[j]; result.add(eachNotDropped); } return result; } } return result; } return RandomAccessListIterate.dropWhile(list, predicate); } public static <T> PartitionMutableList<T> partitionWhile(ArrayList<T> list, Predicate<? super T> predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { PartitionMutableList<T> result = new PartitionFastList<T>(); MutableList<T> selected = result.getSelected(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { T each = elements[i]; if (predicate.accept(each)) { selected.add(each); } else { MutableList<T> rejected = result.getRejected(); rejected.add(each); for (int j = i + 1; j < size; j++) { rejected.add(elements[j]); } return result; } } return result; } return RandomAccessListIterate.partitionWhile(list, predicate); } private static boolean canAccessInternalArray(ArrayList<?> list) { return ArrayListIterate.ELEMENT_DATA_FIELD != null && list.getClass() == ArrayList.class; } private static boolean isOptimizableArrayList(ArrayList<?> list, int newSize) { return newSize > MIN_DIRECT_ARRAY_ACCESS_SIZE && ArrayListIterate.ELEMENT_DATA_FIELD != null && list.getClass() == ArrayList.class; } private static <T> T[] getInternalArray(ArrayList<T> list) { try { return (T[]) ArrayListIterate.ELEMENT_DATA_FIELD.get(list); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } public static <T, K, V> MutableMap<K, V> aggregateInPlaceBy( ArrayList<T> list, Function<? super T, ? extends K> groupBy, Function0<? extends V> zeroValueFactory, Procedure2<? super V, ? super T> mutatingAggregator) { MutableMap<K, V> map = UnifiedMap.newMap(); ArrayListIterate.forEach(list, new MutatingAggregationProcedure<T, K, V>(map, groupBy, zeroValueFactory, mutatingAggregator)); return map; } public static <T, K, V> MutableMap<K, V> aggregateBy( ArrayList<T> list, Function<? super T, ? extends K> groupBy, Function0<? extends V> zeroValueFactory, Function2<? super V, ? super T, ? extends V> nonMutatingAggregator) { MutableMap<K, V> map = UnifiedMap.newMap(); ArrayListIterate.forEach(list, new NonMutatingAggregationProcedure<T, K, V>(map, groupBy, zeroValueFactory, nonMutatingAggregator)); return map; } }