All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gs.collections.impl.list.mutable.FastList Maven / Gradle / Ivy

Go to download

GS Collections is a collections framework for Java. It has JDK-compatible List, Set and Map implementations with a rich API and set of utility classes that work with any JDK compatible Collections, Arrays, Maps or Strings. The iteration protocol was inspired by the Smalltalk collection framework.

There is a newer version: 7.0.3
Show newest version
/*
 * 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.list.mutable;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;

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.map.primitive.ObjectDoubleMap;
import com.gs.collections.api.map.primitive.ObjectLongMap;
import com.gs.collections.api.multimap.MutableMultimap;
import com.gs.collections.api.ordered.OrderedIterable;
import com.gs.collections.api.partition.list.PartitionMutableList;
import com.gs.collections.api.tuple.Twin;
import com.gs.collections.impl.block.factory.Comparators;
import com.gs.collections.impl.block.factory.Predicates2;
import com.gs.collections.impl.block.factory.Procedures2;
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.parallel.BatchIterable;
import com.gs.collections.impl.partition.list.PartitionFastList;
import com.gs.collections.impl.utility.ArrayIterate;
import com.gs.collections.impl.utility.ArrayListIterate;
import com.gs.collections.impl.utility.Iterate;
import com.gs.collections.impl.utility.ListIterate;
import com.gs.collections.impl.utility.internal.InternalArrayIterate;
import com.gs.collections.impl.utility.internal.RandomAccessListIterate;
import net.jcip.annotations.NotThreadSafe;

/**
 * FastList is an attempt to provide the same functionality as ArrayList without the support for concurrent
 * modification exceptions.  It also attempts to correct the problem with subclassing ArrayList
 * in that the data elements are protected, not private.  It is this issue that caused this class
 * to be created in the first place.  The intent was to provide optimized internal iterators which use direct access
 * against the array of items, which is currently not possible by subclassing ArrayList.
 * 

* An empty FastList created by calling the default constructor starts with a shared reference to a static * empty array (DEFAULT_SIZED_EMPTY_ARRAY). This makes empty FastLists very memory efficient. The * first call to add will lazily create an array of size 10. *

* An empty FastList created by calling the pre-size constructor with a value of 0 (new FastList(0)) starts * with a shared reference to a static empty array (ZERO_SIZED_ARRAY). This makes FastLists presized to 0 very * memory efficient as well. The first call to add will lazily create an array of size 1. */ @NotThreadSafe public class FastList extends AbstractMutableList implements Externalizable, RandomAccess, BatchIterable { private static final long serialVersionUID = 1L; private static final Object[] DEFAULT_SIZED_EMPTY_ARRAY = {}; private static final Object[] ZERO_SIZED_ARRAY = {}; private static final int MAXIMUM_ARRAY_SIZE = Integer.MAX_VALUE - 8; protected int size; protected transient T[] items = (T[]) DEFAULT_SIZED_EMPTY_ARRAY; public FastList() { } public FastList(int initialCapacity) { this.items = initialCapacity == 0 ? (T[]) ZERO_SIZED_ARRAY : (T[]) new Object[initialCapacity]; } protected FastList(T[] array) { this(array.length, array); } protected FastList(int size, T[] array) { this.size = size; this.items = array; } public FastList(Collection source) { this.items = (T[]) source.toArray(); this.size = this.items.length; } public static FastList newList() { return new FastList(); } public static FastList wrapCopy(E... array) { E[] newArray = (E[]) new Object[array.length]; System.arraycopy(array, 0, newArray, 0, array.length); return new FastList(newArray); } public static FastList newList(int initialCapacity) { return new FastList(initialCapacity); } public static FastList newList(Iterable source) { return FastList.newListWith((E[]) Iterate.toArray(source)); } /** * Creates a new list using the passed {@code elements} argument as the backing store. *

* !!! WARNING: This method uses the passed in array, so can be very unsafe if the original * array is held onto anywhere else. !!! */ public static FastList newListWith(E... elements) { return new FastList(elements); } /** * Creates a new FastList pre-sized to the specified size filled with default values generated by the specified function. * * @since 3.0 */ public static FastList newWithNValues(int size, Function0 factory) { FastList newFastList = FastList.newList(size); for (int i = 0; i < size; i++) { newFastList.add(factory.value()); } return newFastList; } @Override public FastList clone() { FastList result = (FastList) super.clone(); if (this.items.length > 0) { result.items = this.items.clone(); } return result; } public void clear() { Arrays.fill(this.items, null); this.size = 0; } @Override public void forEach(int from, int to, Procedure procedure) { ListIterate.rangeCheck(from, to, this.size); InternalArrayIterate.forEachWithoutChecks(this.items, from, to, procedure); } @Override public void forEachWithIndex(int from, int to, ObjectIntProcedure objectIntProcedure) { ListIterate.rangeCheck(from, to, this.size); InternalArrayIterate.forEachWithIndexWithoutChecks(this.items, from, to, objectIntProcedure); } public void batchForEach(Procedure procedure, int sectionIndex, int sectionCount) { InternalArrayIterate.batchForEach(procedure, this.items, this.size, sectionIndex, sectionCount); } public int getBatchCount(int batchSize) { return Math.max(1, this.size() / batchSize); } public E[] toArray(E[] array, int sourceFromIndex, int sourceToIndex, int destinationIndex) { System.arraycopy(this.items, sourceFromIndex, array, destinationIndex, sourceToIndex - sourceFromIndex + 1); return array; } public E[] toArray(int sourceFromIndex, int sourceToIndex) { return this.toArray((E[]) new Object[sourceToIndex - sourceFromIndex + 1], sourceFromIndex, sourceToIndex, 0); } @Override public FastList sortThis(Comparator comparator) { Arrays.sort(this.items, 0, this.size, comparator); return this; } @Override public FastList sortThis() { Arrays.sort(this.items, 0, this.size); return this; } @Override public FastList reverseThis() { ArrayIterate.reverse(this.items, this.size); return this; } @Override public boolean addAll(Collection source) { if (source.isEmpty()) { return false; } if (source.getClass() == FastList.class) { this.addAllFastList((FastList) source); } else if (source.getClass() == ArrayList.class) { this.addAllArrayList((ArrayList) source); } else if (source instanceof List && source instanceof RandomAccess) { this.addAllRandomAccessList((List) source); } else { this.addAllCollection(source); } return true; } private void addAllFastList(FastList source) { int sourceSize = source.size(); int newSize = this.size + sourceSize; this.ensureCapacity(newSize); System.arraycopy(source.items, 0, this.items, this.size, sourceSize); this.size = newSize; } private void addAllArrayList(ArrayList source) { int sourceSize = source.size(); int newSize = this.size + sourceSize; this.ensureCapacity(newSize); ArrayListIterate.toArray(source, this.items, this.size, sourceSize); this.size = newSize; } private void addAllRandomAccessList(List source) { int sourceSize = source.size(); int newSize = this.size + sourceSize; this.ensureCapacity(newSize); RandomAccessListIterate.toArray(source, this.items, this.size, sourceSize); this.size = newSize; } private void addAllCollection(Collection source) { this.ensureCapacity(this.size + source.size()); Iterate.forEachWith(source, Procedures2.addToCollection(), this); } @Override public boolean containsAll(Collection source) { return Iterate.allSatisfyWith(source, Predicates2.in(), this); } @Override public boolean containsAllArguments(Object... source) { return ArrayIterate.allSatisfyWith(source, Predicates2.in(), this); } @Override public E[] toArray(E[] array) { if (array.length < this.size) { array = (E[]) Array.newInstance(array.getClass().getComponentType(), this.size); } System.arraycopy(this.items, 0, array, 0, this.size); if (array.length > this.size) { array[this.size] = null; } return array; } @Override public Object[] toArray() { return this.copyItemsWithNewCapacity(this.size); } public T[] toTypedArray(Class clazz) { T[] array = (T[]) Array.newInstance(clazz, this.size); System.arraycopy(this.items, 0, array, 0, this.size); return array; } private void throwOutOfBounds(int index) { throw this.newIndexOutOfBoundsException(index); } public T set(int index, T element) { T previous = this.get(index); this.items[index] = element; return previous; } @Override public int indexOf(Object object) { return InternalArrayIterate.indexOf(this.items, this.size, object); } @Override public int lastIndexOf(Object object) { return InternalArrayIterate.lastIndexOf(this.items, this.size, object); } public void trimToSize() { if (this.size < this.items.length) { this.transferItemsToNewArrayWithCapacity(this.size); } } /** * Express load factor as 0.25 to trim a collection with more than 25% excess capacity */ public boolean trimToSizeIfGreaterThanPercent(double loadFactor) { double excessCapacity = 1.0 - (double) this.size / (double) this.items.length; if (excessCapacity > loadFactor) { this.trimToSize(); return true; } return false; } public void ensureCapacity(int minCapacity) { int oldCapacity = this.items.length; if (minCapacity > oldCapacity) { int newCapacity = Math.max(this.sizePlusFiftyPercent(oldCapacity), minCapacity); this.transferItemsToNewArrayWithCapacity(newCapacity); } } private void transferItemsToNewArrayWithCapacity(int newCapacity) { this.items = (T[]) this.copyItemsWithNewCapacity(newCapacity); } private Object[] copyItemsWithNewCapacity(int newCapacity) { Object[] newItems = new Object[newCapacity]; System.arraycopy(this.items, 0, newItems, 0, Math.min(this.size, newCapacity)); return newItems; } public FastList with(T element1, T element2) { this.add(element1); this.add(element2); return this; } public FastList with(T element1, T element2, T element3) { this.add(element1); this.add(element2); this.add(element3); return this; } public FastList with(T... elements) { return this.withArrayCopy(elements, 0, elements.length); } public FastList withArrayCopy(T[] elements, int begin, int length) { this.ensureCapacity(this.size + length); System.arraycopy(elements, begin, this.items, this.size, length); this.size += length; return this; } @Override public T getFirst() { return this.isEmpty() ? null : this.items[0]; } @Override public T getLast() { return this.isEmpty() ? null : this.items[this.size() - 1]; } @Override public FastListMultimap groupBy(Function function) { return this.groupBy(function, FastListMultimap.newMultimap()); } @Override public > R groupBy(Function function, R target) { return InternalArrayIterate.groupBy(this.items, this.size, function, target); } @Override public FastListMultimap groupByEach(Function> function) { return this.groupByEach(function, FastListMultimap.newMultimap()); } @Override public > R groupByEach( Function> function, R target) { return InternalArrayIterate.groupByEach(this.items, this.size, function, target); } @Override public MutableMap groupByUniqueKey(Function function) { return this.groupByUniqueKey(function, UnifiedMap.newMap()); } @Override public > R groupByUniqueKey(Function function, R target) { return InternalArrayIterate.groupByUniqueKey(this.items, this.size, function, target); } @Override public void appendString(Appendable appendable, String start, String separator, String end) { InternalArrayIterate.appendString(this, this.items, this.size, appendable, start, separator, end); } @Override public MutableList take(int count) { return RandomAccessListIterate.take(this, count); } @Override public MutableList drop(int count) { return RandomAccessListIterate.drop(this, count); } @Override public PartitionFastList partition(Predicate predicate) { return InternalArrayIterate.partition(this.items, this.size, predicate); } @Override public

PartitionFastList partitionWith(Predicate2 predicate, P parameter) { return InternalArrayIterate.partitionWith(this.items, this.size, predicate, parameter); } @Override public void each(Procedure procedure) { for (int i = 0; i < this.size; i++) { procedure.value(this.items[i]); } } public void forEachIf(Predicate predicate, Procedure procedure) { for (int i = 0; i < this.size; i++) { T item = this.items[i]; if (predicate.accept(item)) { procedure.value(item); } } } @Override public void forEachWithIndex(ObjectIntProcedure objectIntProcedure) { InternalArrayIterate.forEachWithIndex(this.items, this.size, objectIntProcedure); } @Override public

void forEachWith(Procedure2 procedure, P parameter) { for (int i = 0; i < this.size; i++) { procedure.value(this.items[i], parameter); } } @Override public FastList select(Predicate predicate) { return this.select(predicate, FastList.newList()); } @Override public > R select(Predicate predicate, R target) { return InternalArrayIterate.select(this.items, this.size, predicate, target); } @Override public

FastList selectWith(Predicate2 predicate, P parameter) { return this.selectWith(predicate, parameter, FastList.newList()); } @Override public > R selectWith( Predicate2 predicate, P parameter, R target) { return InternalArrayIterate.selectWith(this.items, this.size, predicate, parameter, target); } @Override public FastList reject(Predicate predicate) { return this.reject(predicate, FastList.newList()); } @Override public > R reject(Predicate predicate, R target) { return InternalArrayIterate.reject(this.items, this.size, predicate, target); } @Override public

FastList rejectWith(Predicate2 predicate, P parameter) { return this.rejectWith(predicate, parameter, FastList.newList()); } @Override public > R rejectWith( Predicate2 predicate, P parameter, R target) { return InternalArrayIterate.rejectWith(this.items, this.size, predicate, parameter, target); } @Override public

Twin> selectAndRejectWith( Predicate2 predicate, P parameter) { return InternalArrayIterate.selectAndRejectWith(this.items, this.size, predicate, parameter); } @Override public FastList selectInstancesOf(Class clazz) { return InternalArrayIterate.selectInstancesOf(this.items, this.size, clazz); } @Override public boolean removeIf(Predicate predicate) { int currentFilledIndex = 0; for (int i = 0; i < this.size; i++) { T item = this.items[i]; if (!predicate.accept(item)) { // keep it if (currentFilledIndex != i) { this.items[currentFilledIndex] = item; } currentFilledIndex++; } } boolean changed = currentFilledIndex < this.size; this.wipeAndResetTheEnd(currentFilledIndex); return changed; } private void wipeAndResetTheEnd(int newCurrentFilledIndex) { for (int i = newCurrentFilledIndex; i < this.size; i++) { this.items[i] = null; } this.size = newCurrentFilledIndex; } @Override public

boolean removeIfWith(Predicate2 predicate, P parameter) { int currentFilledIndex = 0; for (int i = 0; i < this.size; i++) { T item = this.items[i]; if (!predicate.accept(item, parameter)) { // keep it if (currentFilledIndex != i) { this.items[currentFilledIndex] = item; } currentFilledIndex++; } } boolean changed = currentFilledIndex < this.size; this.wipeAndResetTheEnd(currentFilledIndex); return changed; } @Override public FastList collect(Function function) { return this.collect(function, FastList.newList(this.size())); } @Override public MutableBooleanList collectBoolean(BooleanFunction booleanFunction) { return this.collectBoolean(booleanFunction, new BooleanArrayList(this.size)); } @Override public R collectBoolean(BooleanFunction booleanFunction, R target) { for (int i = 0; i < this.size; i++) { target.add(booleanFunction.booleanValueOf(this.items[i])); } return target; } @Override public MutableByteList collectByte(ByteFunction byteFunction) { return this.collectByte(byteFunction, new ByteArrayList(this.size)); } @Override public R collectByte(ByteFunction byteFunction, R target) { for (int i = 0; i < this.size; i++) { target.add(byteFunction.byteValueOf(this.items[i])); } return target; } @Override public MutableCharList collectChar(CharFunction charFunction) { return this.collectChar(charFunction, new CharArrayList(this.size)); } @Override public R collectChar(CharFunction charFunction, R target) { for (int i = 0; i < this.size; i++) { target.add(charFunction.charValueOf(this.items[i])); } return target; } @Override public MutableDoubleList collectDouble(DoubleFunction doubleFunction) { return this.collectDouble(doubleFunction, new DoubleArrayList(this.size)); } @Override public R collectDouble(DoubleFunction doubleFunction, R target) { for (int i = 0; i < this.size; i++) { target.add(doubleFunction.doubleValueOf(this.items[i])); } return target; } @Override public MutableFloatList collectFloat(FloatFunction floatFunction) { return this.collectFloat(floatFunction, new FloatArrayList(this.size)); } @Override public R collectFloat(FloatFunction floatFunction, R target) { for (int i = 0; i < this.size; i++) { target.add(floatFunction.floatValueOf(this.items[i])); } return target; } @Override public MutableIntList collectInt(IntFunction intFunction) { return this.collectInt(intFunction, new IntArrayList(this.size)); } @Override public R collectInt(IntFunction intFunction, R target) { for (int i = 0; i < this.size; i++) { target.add(intFunction.intValueOf(this.items[i])); } return target; } @Override public MutableLongList collectLong(LongFunction longFunction) { return this.collectLong(longFunction, new LongArrayList(this.size)); } @Override public R collectLong(LongFunction longFunction, R target) { for (int i = 0; i < this.size; i++) { target.add(longFunction.longValueOf(this.items[i])); } return target; } @Override public MutableShortList collectShort(ShortFunction shortFunction) { return this.collectShort(shortFunction, new ShortArrayList(this.size)); } @Override public R collectShort(ShortFunction shortFunction, R target) { for (int i = 0; i < this.size; i++) { target.add(shortFunction.shortValueOf(this.items[i])); } return target; } @Override public > R collect(Function function, R target) { return InternalArrayIterate.collect(this.items, this.size, function, target); } @Override public FastList flatCollect(Function> function) { return this.flatCollect(function, FastList.newList(this.size())); } @Override public > R flatCollect( Function> function, R target) { return InternalArrayIterate.flatCollect(this.items, this.size, function, target); } @Override public FastList collectWith(Function2 function, P parameter) { return this.collectWith(function, parameter, FastList.newList(this.size())); } @Override public > R collectWith( Function2 function, P parameter, R target) { return InternalArrayIterate.collectWith(this.items, this.size, function, parameter, target); } @Override public FastList collectIf( Predicate predicate, Function function) { return this.collectIf(predicate, function, FastList.newList()); } @Override public > R collectIf( Predicate predicate, Function function, R target) { return InternalArrayIterate.collectIf(this.items, this.size, predicate, function, target); } @Override public T detect(Predicate predicate) { return InternalArrayIterate.detect(this.items, this.size, predicate); } @Override public T detectIfNone(Predicate predicate, Function0 defaultValueBlock) { T result = this.detect(predicate); return result == null ? defaultValueBlock.value() : result; } @Override public int detectIndex(Predicate predicate) { return InternalArrayIterate.detectIndex(this.items, this.size, predicate); } @Override public int detectLastIndex(Predicate predicate) { return InternalArrayIterate.detectLastIndex(this.items, this.size, predicate); } @Override public T min(Comparator comparator) { return InternalArrayIterate.min(this.items, this.size, comparator); } @Override public T max(Comparator comparator) { return InternalArrayIterate.max(this.items, this.size, comparator); } @Override public T min() { return InternalArrayIterate.min(this.items, this.size); } @Override public T max() { return InternalArrayIterate.max(this.items, this.size); } @Override public > T minBy(Function function) { return InternalArrayIterate.minBy(this.items, this.size, function); } @Override public > T maxBy(Function function) { return InternalArrayIterate.maxBy(this.items, this.size, function); } @Override public

T detectWith(Predicate2 predicate, P parameter) { return InternalArrayIterate.detectWith(this.items, this.size, predicate, parameter); } @Override public

T detectWithIfNone( Predicate2 predicate, P parameter, Function0 defaultValueBlock) { T result = this.detectWith(predicate, parameter); return result == null ? defaultValueBlock.value() : result; } public T get(int index) { if (index < this.size) { return this.items[index]; } throw this.newIndexOutOfBoundsException(index); } private IndexOutOfBoundsException newIndexOutOfBoundsException(int index) { return new IndexOutOfBoundsException("Index: " + index + " Size: " + this.size); } @Override public boolean add(T newItem) { if (this.items.length == this.size) { this.ensureCapacityForAdd(); } this.items[this.size++] = newItem; return true; } private void ensureCapacityForAdd() { if (this.items == DEFAULT_SIZED_EMPTY_ARRAY) { this.items = (T[]) new Object[10]; } else { this.transferItemsToNewArrayWithCapacity(this.sizePlusFiftyPercent(this.size)); } } public void add(int index, T element) { if (index > -1 && index < this.size) { this.addAtIndex(index, element); } else if (index == this.size) { this.add(element); } else { this.throwOutOfBounds(index); } } private void addAtIndex(int index, T element) { int oldSize = this.size++; if (this.items.length == oldSize) { T[] newItems = (T[]) new Object[this.sizePlusFiftyPercent(oldSize)]; if (index > 0) { System.arraycopy(this.items, 0, newItems, 0, index); } System.arraycopy(this.items, index, newItems, index + 1, oldSize - index); this.items = newItems; } else { System.arraycopy(this.items, index, this.items, index + 1, oldSize - index); } this.items[index] = element; } private int sizePlusFiftyPercent(int oldSize) { int result = oldSize + (oldSize >> 1) + 1; return result < oldSize ? MAXIMUM_ARRAY_SIZE : result; } public T remove(int index) { T previous = this.get(index); int totalOffset = this.size - index - 1; if (totalOffset > 0) { System.arraycopy(this.items, index + 1, this.items, index, totalOffset); } this.items[--this.size] = null; return previous; } @Override public boolean remove(Object object) { int index = this.indexOf(object); if (index >= 0) { this.remove(index); return true; } return false; } public boolean addAll(int index, Collection source) { if (index > this.size || index < 0) { this.throwOutOfBounds(index); } if (source.isEmpty()) { return false; } if (source.getClass() == FastList.class) { this.addAllFastListAtIndex((FastList) source, index); } else if (source.getClass() == ArrayList.class) { this.addAllArrayListAtIndex((ArrayList) source, index); } else if (source instanceof List && source instanceof RandomAccess) { this.addAllRandomAccessListAtIndex((List) source, index); } else { this.addAllCollectionAtIndex(source, index); } return true; } private void addAllFastListAtIndex(FastList source, int index) { int sourceSize = source.size(); int newSize = this.size + sourceSize; this.ensureCapacity(newSize); this.shiftElementsAtIndex(index, sourceSize); System.arraycopy(source.items, 0, this.items, index, sourceSize); this.size = newSize; } private void addAllArrayListAtIndex(ArrayList source, int index) { int sourceSize = source.size(); int newSize = this.size + sourceSize; this.ensureCapacity(newSize); this.shiftElementsAtIndex(index, sourceSize); ArrayListIterate.toArray(source, this.items, index, sourceSize); this.size = newSize; } private void addAllRandomAccessListAtIndex(List source, int index) { int sourceSize = source.size(); int newSize = this.size + sourceSize; this.ensureCapacity(newSize); this.shiftElementsAtIndex(index, sourceSize); RandomAccessListIterate.toArray(source, this.items, index, sourceSize); this.size = newSize; } private void addAllCollectionAtIndex(Collection source, int index) { Object[] newItems = source.toArray(); int sourceSize = newItems.length; int newSize = this.size + sourceSize; this.ensureCapacity(newSize); this.shiftElementsAtIndex(index, sourceSize); this.size = newSize; System.arraycopy(newItems, 0, this.items, index, sourceSize); } private void shiftElementsAtIndex(int index, int sourceSize) { int numberToMove = this.size - index; if (numberToMove > 0) { System.arraycopy(this.items, index, this.items, index + sourceSize, numberToMove); } } public int size() { return this.size; } @Override public int count(Predicate predicate) { return InternalArrayIterate.count(this.items, this.size, predicate); } @Override public

int countWith(Predicate2 predicate, P parameter) { return InternalArrayIterate.countWith(this.items, this.size, predicate, parameter); } @Override public boolean corresponds(OrderedIterable other, Predicate2 predicate) { return InternalArrayIterate.corresponds(this.items, this.size, other, predicate); } @Override public boolean anySatisfy(Predicate predicate) { return InternalArrayIterate.anySatisfy(this.items, this.size, predicate); } @Override public

boolean anySatisfyWith(Predicate2 predicate, P parameter) { return InternalArrayIterate.anySatisfyWith(this.items, this.size, predicate, parameter); } @Override public boolean allSatisfy(Predicate predicate) { return InternalArrayIterate.allSatisfy(this.items, this.size, predicate); } @Override public

boolean allSatisfyWith(Predicate2 predicate, P parameter) { return InternalArrayIterate.allSatisfyWith(this.items, this.size, predicate, parameter); } @Override public boolean noneSatisfy(Predicate predicate) { return InternalArrayIterate.noneSatisfy(this.items, this.size, predicate); } @Override public

boolean noneSatisfyWith(Predicate2 predicate, P parameter) { return InternalArrayIterate.noneSatisfyWith(this.items, this.size, predicate, parameter); } @Override public IV injectInto(IV injectedValue, Function2 function) { IV result = injectedValue; for (int i = 0; i < this.size; i++) { result = function.value(result, this.items[i]); } return result; } @Override public int injectInto(int injectedValue, IntObjectToIntFunction function) { int result = injectedValue; for (int i = 0; i < this.size; i++) { result = function.intValueOf(result, this.items[i]); } return result; } @Override public long injectInto(long injectedValue, LongObjectToLongFunction function) { long result = injectedValue; for (int i = 0; i < this.size; i++) { result = function.longValueOf(result, this.items[i]); } return result; } @Override public double injectInto(double injectedValue, DoubleObjectToDoubleFunction function) { double result = injectedValue; for (int i = 0; i < this.size; i++) { result = function.doubleValueOf(result, this.items[i]); } return result; } @Override public float injectInto(float injectedValue, FloatObjectToFloatFunction function) { float result = injectedValue; for (int i = 0; i < this.size; i++) { result = function.floatValueOf(result, this.items[i]); } return result; } @Override public MutableList distinct() { return InternalArrayIterate.distinct(this.items, this.size); } @Override public MutableList distinct(HashingStrategy hashingStrategy) { return InternalArrayIterate.distinct(this.items, this.size, hashingStrategy); } @Override public long sumOfInt(IntFunction function) { return InternalArrayIterate.sumOfInt(this.items, this.size, function); } @Override public long sumOfLong(LongFunction function) { return InternalArrayIterate.sumOfLong(this.items, this.size, function); } @Override public double sumOfFloat(FloatFunction function) { return InternalArrayIterate.sumOfFloat(this.items, this.size, function); } @Override public double sumOfDouble(DoubleFunction function) { return InternalArrayIterate.sumOfDouble(this.items, this.size, function); } @Override public ObjectLongMap sumByInt(Function groupBy, IntFunction function) { return InternalArrayIterate.sumByInt(this.items, this.size, groupBy, function); } @Override public ObjectLongMap sumByLong(Function groupBy, LongFunction function) { return InternalArrayIterate.sumByLong(this.items, this.size, groupBy, function); } @Override public ObjectDoubleMap sumByFloat(Function groupBy, FloatFunction function) { return InternalArrayIterate.sumByFloat(this.items, this.size, groupBy, function); } @Override public ObjectDoubleMap sumByDouble(Function groupBy, DoubleFunction function) { return InternalArrayIterate.sumByDouble(this.items, this.size, groupBy, function); } @Override public IV injectIntoWith( IV injectValue, Function3 function, P parameter) { IV result = injectValue; for (int i = 0; i < this.size; i++) { result = function.value(result, this.items[i], parameter); } return result; } @Override public FastList toList() { return FastList.newList(this); } @Override public FastList toSortedList() { return this.toSortedList(Comparators.naturalOrder()); } @Override public FastList toSortedList(Comparator comparator) { return FastList.newList(this).sortThis(comparator); } @Override public MutableList takeWhile(Predicate predicate) { int endIndex = this.detectNotIndex(predicate); T[] result = (T[]) new Object[endIndex]; System.arraycopy(this.items, 0, result, 0, endIndex); return FastList.newListWith(result); } @Override public MutableList dropWhile(Predicate predicate) { int startIndex = this.detectNotIndex(predicate); int resultSize = this.size() - startIndex; T[] result = (T[]) new Object[resultSize]; System.arraycopy(this.items, startIndex, result, 0, resultSize); return FastList.newListWith(result); } @Override public PartitionMutableList partitionWhile(Predicate predicate) { PartitionMutableList result = new PartitionFastList(); FastList selected = (FastList) result.getSelected(); FastList rejected = (FastList) result.getRejected(); int partitionIndex = this.detectNotIndex(predicate); int rejectedSize = this.size() - partitionIndex; selected.withArrayCopy(this.items, 0, partitionIndex); rejected.withArrayCopy(this.items, partitionIndex, rejectedSize); return result; } private int detectNotIndex(Predicate predicate) { for (int index = 0; index < this.size; index++) { if (!predicate.accept(this.items[index])) { return index; } } return this.size; } @Override public boolean equals(Object that) { if (that == this) { return true; } if (!(that instanceof List)) { return false; } if (that instanceof FastList) { return this.fastListEquals((FastList) that); } return InternalArrayIterate.arrayEqualsList(this.items, this.size, (List) that); } public boolean fastListEquals(FastList that) { if (this.size != that.size) { return false; } for (int i = 0; i < this.size; i++) { if (!Comparators.nullSafeEquals(this.items[i], that.items[i])) { return false; } } return true; } @Override public int hashCode() { int hashCode = 1; for (int i = 0; i < this.size; i++) { T item = this.items[i]; hashCode = 31 * hashCode + (item == null ? 0 : item.hashCode()); } return hashCode; } public void writeExternal(ObjectOutput out) throws IOException { out.writeInt(this.size()); for (int i = 0; i < this.size; i++) { out.writeObject(this.items[i]); } } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { this.size = in.readInt(); this.items = (T[]) new Object[this.size]; for (int i = 0; i < this.size; i++) { this.items[i] = (T) in.readObject(); } } }