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

com.gs.collections.impl.utility.ArrayListIterate Maven / Gradle / Ivy

/*
 * Copyright 2013 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.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

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.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  ArrayList select(ArrayList list, Predicate predicate)
    {
        return ArrayListIterate.select(list, predicate, new ArrayList());
    }

    /**
     * @see Iterate#selectWith(Iterable, Predicate2, Object)
     */
    public static  ArrayList selectWith(
            ArrayList list,
            Predicate2 predicate,
            IV injectedValue)
    {
        return ArrayListIterate.selectWith(list, predicate, injectedValue, new ArrayList());
    }

    /**
     * @see Iterate#select(Iterable, Predicate, Collection)
     */
    public static > R select(
            ArrayList list,
            Predicate 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 > R selectWith(
            ArrayList list,
            Predicate2 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  MutableList selectInstancesOf(
            ArrayList list,
            Class clazz)
    {
        int size = list.size();
        FastList 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  int count(ArrayList list, Predicate 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  int countWith(
            ArrayList list,
            Predicate2 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  ArrayList collectIf(
            ArrayList list,
            Predicate predicate,
            Function function)
    {
        return ArrayListIterate.collectIf(list, predicate, function, new ArrayList());
    }

    /**
     * @see Iterate#collectIf(Iterable, Predicate, Function, Collection)
     */
    public static > R collectIf(
            ArrayList list,
            Predicate predicate,
            Function 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  ArrayList reject(ArrayList list, Predicate predicate)
    {
        return ArrayListIterate.reject(list, predicate, new ArrayList());
    }

    /**
     * @see Iterate#rejectWith(Iterable, Predicate2, Object)
     */
    public static  ArrayList rejectWith(
            ArrayList list,
            Predicate2 predicate,
            IV injectedValue)
    {
        return ArrayListIterate.rejectWith(list, predicate, injectedValue, new ArrayList());
    }

    /**
     * @see Iterate#reject(Iterable, Predicate, Collection)
     */
    public static > R reject(
            ArrayList list,
            Predicate 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 > R rejectWith(
            ArrayList list,
            Predicate2 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  ArrayList collect(
            ArrayList list,
            Function function)
    {
        return ArrayListIterate.collect(list, function, new ArrayList(list.size()));
    }

    /**
     * @see Iterate#collectBoolean(Iterable, BooleanFunction)
     */
    public static  MutableBooleanList collectBoolean(
            ArrayList list,
            BooleanFunction 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  R collectBoolean(ArrayList list, BooleanFunction 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  R collectBooleanFromInternalArray(ArrayList source, BooleanFunction 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  MutableByteList collectByte(
            ArrayList list,
            ByteFunction 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  R collectByte(ArrayList list, ByteFunction 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  R collectByteFromInternalArray(ArrayList source, ByteFunction 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  MutableCharList collectChar(
            ArrayList list,
            CharFunction 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  R collectChar(ArrayList list, CharFunction 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  R collectCharFromInternalArray(ArrayList source, CharFunction 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  MutableDoubleList collectDouble(
            ArrayList list,
            DoubleFunction 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  R collectDouble(ArrayList list, DoubleFunction 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  R collectDoubleFromInternalArray(ArrayList source, DoubleFunction 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  MutableFloatList collectFloat(
            ArrayList list,
            FloatFunction 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  R collectFloat(ArrayList list, FloatFunction 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  R collectFloatFromInternalArray(ArrayList source, FloatFunction 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  MutableIntList collectInt(
            ArrayList list,
            IntFunction 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  R collectInt(ArrayList list, IntFunction 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  R collectIntFromInternalArray(ArrayList source, IntFunction 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  MutableLongList collectLong(
            ArrayList list,
            LongFunction 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  R collectLong(ArrayList list, LongFunction 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  R collectLongFromInternalArray(ArrayList source, LongFunction 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  MutableShortList collectShort(
            ArrayList list,
            ShortFunction 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  R collectShort(ArrayList list, ShortFunction 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  R collectShortFromInternalArray(ArrayList source, ShortFunction 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 > R collect(
            ArrayList list,
            Function 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  ArrayList flatCollect(
            ArrayList list,
            Function> function)
    {
        return ArrayListIterate.flatCollect(list, function, new ArrayList(list.size()));
    }

    /**
     * @see Iterate#flatCollect(Iterable, Function, Collection)
     */
    public static > R flatCollect(
            ArrayList list,
            Function> 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  void forEach(ArrayList list, Procedure 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  void reverseForEach(ArrayList list, Procedure 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.
     * 

*

*

e.g.
     * ArrayList people = new ArrayList(FastList.newListWith(ted, mary, bob, sally));
     * ArrayListIterate.forEach(people, 0, 1, new Procedure()
     * {
     *     public void value(Person person)
     *     {
     *          LOGGER.info(person.getName());
     *     }
     * });
     * 
*

* This code would output ted and mary's names. */ public static void forEach(ArrayList list, int from, int to, Procedure 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. *

*

*

e.g.
     * ArrayList people = new ArrayList(FastList.newListWith(ted, mary, bob, sally));
     * ArrayListIterate.forEachWithIndex(people, 0, 1, new ObjectIntProcedure()
     * {
     *     public void value(Person person, int index)
     *     {
     *          LOGGER.info(person.getName() + " at index: " + index);
     *     }
     * });
     * 
*

* This code would output ted and mary's names. */ public static void forEachWithIndex( ArrayList list, int from, int to, ObjectIntProcedure 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 void forEachInBoth( ArrayList list1, ArrayList list2, Procedure2 procedure) { RandomAccessListIterate.forEachInBoth(list1, list2, procedure); } /** * @see Iterate#forEachWithIndex(Iterable, ObjectIntProcedure) */ public static void forEachWithIndex(ArrayList list, ObjectIntProcedure 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 detect(ArrayList list, Predicate 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 detectWith( ArrayList list, Predicate2 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 detectIfNone(ArrayList list, Predicate predicate, T ifNone) { T result = ArrayListIterate.detect(list, predicate); return result == null ? ifNone : result; } /** * @see Iterate#detectWithIfNone(Iterable, Predicate2, Object, Object) */ public static T detectWithIfNone( ArrayList list, Predicate2 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 IV injectInto( IV injectValue, ArrayList list, Function2 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 int injectInto( int injectValue, ArrayList list, IntObjectToIntFunction 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 long injectInto( long injectValue, ArrayList list, LongObjectToLongFunction 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 double injectInto( double injectValue, ArrayList list, DoubleObjectToDoubleFunction 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 float injectInto( float injectValue, ArrayList list, FloatObjectToFloatFunction 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 boolean anySatisfy(ArrayList list, Predicate 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 boolean anySatisfyWith( ArrayList list, Predicate2 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 boolean allSatisfy(ArrayList list, Predicate 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 boolean allSatisfyWith( ArrayList list, Predicate2 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 boolean noneSatisfy(ArrayList list, Predicate 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 boolean noneSatisfyWith( ArrayList list, Predicate2 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 Twin> selectAndRejectWith( ArrayList list, Predicate2 predicate, P parameter) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableList positiveResult = Lists.mutable.of(); MutableList negativeResult = Lists.mutable.of(); 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 PartitionMutableList partition(ArrayList list, Predicate predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { PartitionFastList partitionFastList = new PartitionFastList(); MutableList selected = partitionFastList.getSelected(); MutableList rejected = partitionFastList.getRejected(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { T each = elements[i]; MutableList bucket = predicate.accept(each) ? selected : rejected; bucket.add(each); } return partitionFastList; } return RandomAccessListIterate.partition(list, predicate); } public static PartitionMutableList partitionWith(ArrayList list, Predicate2 predicate, P parameter) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { PartitionFastList partitionFastList = new PartitionFastList(); MutableList selected = partitionFastList.getSelected(); MutableList rejected = partitionFastList.getRejected(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { T each = elements[i]; MutableList 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 int detectIndex(ArrayList list, Predicate 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 int detectIndexWith( ArrayList list, Predicate2 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 Iterate#injectIntoWith(Object, Iterable, Function3, Object) */ public static IV injectIntoWith( IV injectedValue, ArrayList list, Function3 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 void forEachWith( ArrayList list, Procedure2 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 ArrayList collectWith( ArrayList list, Function2 function, P parameter) { return ArrayListIterate.collectWith(list, function, parameter, new ArrayList(list.size())); } /** * @see Iterate#collectWith(Iterable, Function2, Object, Collection) */ public static > R collectWith( ArrayList list, Function2 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 ArrayList removeIf(ArrayList list, Predicate predicate) { 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++; } } wipeAndResetTheEnd(currentFilledIndex, size, elements, list); } else { RandomAccessListIterate.removeIf(list, predicate); } return list; } /** * @see Iterate#removeIfWith(Iterable, Predicate2, Object) */ public static ArrayList removeIfWith( ArrayList list, Predicate2 predicate, P parameter) { 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++; } } wipeAndResetTheEnd(currentFilledIndex, size, elements, list); } else { RandomAccessListIterate.removeIfWith(list, predicate, parameter); } return list; } public static ArrayList distinct(ArrayList list) { return ArrayListIterate.distinct(list, new ArrayList()); } public static > R distinct(ArrayList list, R targetCollection) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableSet seenSoFar = UnifiedSet.newSet(); T[] elements = ArrayListIterate.getInternalArray(list); for (int i = 0; i < size; i++) { if (seenSoFar.add(elements[i])) { targetCollection.add(elements[i]); } } return targetCollection; } return RandomAccessListIterate.distinct(list, targetCollection); } private static void wipeAndResetTheEnd( int newCurrentFilledIndex, int newSize, T[] newElements, ArrayList 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 > ArrayList sortThis(ArrayList 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 ArrayList sortThis(ArrayList list, Comparator comparator) { int size = list.size(); if (size > 1) { if (ArrayListIterate.canAccessInternalArray(list)) { ArrayIterate.sort(ArrayListIterate.getInternalArray(list), size, comparator); } else { Collections.sort(list, comparator); } } return list; } public static void toArray(ArrayList 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 ArrayList take(ArrayList list, int count) { return ArrayListIterate.take(list, count, new ArrayList(count)); } /** * @see Iterate#take(Iterable, int) */ public static > R take(ArrayList list, int count, R targetList) { 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 ArrayList drop(ArrayList list, int count) { return ArrayListIterate.drop(list, count, new ArrayList(list.size() - Math.min(list.size(), count))); } /** * @see Iterate#drop(Iterable, int) */ public static > R drop(ArrayList list, int count, R targetList) { return RandomAccessListIterate.drop(list, count, targetList); } /** * @see Iterate#groupBy(Iterable, Function) */ public static FastListMultimap groupBy( ArrayList list, Function function) { return ArrayListIterate.groupBy(list, function, FastListMultimap.newMultimap()); } /** * @see Iterate#groupBy(Iterable, Function, MutableMultimap) */ public static > R groupBy( ArrayList list, Function 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 FastListMultimap groupByEach( ArrayList list, Function> function) { return ArrayListIterate.groupByEach(list, function, FastListMultimap.newMultimap()); } /** * @see Iterate#groupByEach(Iterable, Function, MutableMultimap) */ public static > R groupByEach( ArrayList list, Function> 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 iterable = function.valueOf(elements[i]); for (V key : iterable) { target.put(key, elements[i]); } } return target; } return RandomAccessListIterate.groupByEach(list, function, target); } /** * @see Iterate#zip(Iterable, Iterable) */ public static MutableList> zip(ArrayList xs, Iterable ys) { return ArrayListIterate.zip(xs, ys, FastList.>newList()); } /** * @see Iterate#zip(Iterable, Iterable, Collection) */ public static >> R zip(ArrayList xs, Iterable ys, R targetCollection) { int size = xs.size(); if (ArrayListIterate.isOptimizableArrayList(xs, size)) { Iterator 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 MutableList> zipWithIndex(ArrayList list) { return ArrayListIterate.zipWithIndex(list, FastList.>newList()); } /** * @see Iterate#zipWithIndex(Iterable, Collection) */ public static >> R zipWithIndex(ArrayList 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 MutableList takeWhile(ArrayList list, Predicate predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableList 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 MutableList dropWhile(ArrayList list, Predicate predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { MutableList 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 PartitionMutableList partitionWhile(ArrayList list, Predicate predicate) { int size = list.size(); if (ArrayListIterate.isOptimizableArrayList(list, size)) { PartitionMutableList result = new PartitionFastList(); MutableList 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 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[] getInternalArray(ArrayList list) { try { return (T[]) ArrayListIterate.ELEMENT_DATA_FIELD.get(list); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } public static MutableMap aggregateInPlaceBy( ArrayList list, Function groupBy, Function0 zeroValueFactory, Procedure2 mutatingAggregator) { MutableMap map = UnifiedMap.newMap(); ArrayListIterate.forEach(list, new MutatingAggregationProcedure(map, groupBy, zeroValueFactory, mutatingAggregator)); return map; } public static MutableMap aggregateBy( ArrayList list, Function groupBy, Function0 zeroValueFactory, Function2 nonMutatingAggregator) { MutableMap map = UnifiedMap.newMap(); ArrayListIterate.forEach(list, new NonMutatingAggregationProcedure(map, groupBy, zeroValueFactory, nonMutatingAggregator)); return map; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy