ArrayUtils.java revision aa43a4ba9f61504a22d10f2c6d233576791e7776
1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/*
2b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Copyright (C) 2006 The Android Open Source Project
3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License");
5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License.
6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at
7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *      http://www.apache.org/licenses/LICENSE-2.0
9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software
11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS,
12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and
14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License.
15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */
16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikpackage com.android.internal.util;
18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
19d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craikimport android.annotation.NonNull;
20b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikimport android.annotation.Nullable;
21b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikimport android.util.ArraySet;
22766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikimport dalvik.system.VMRuntime;
24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
25b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikimport libcore.util.EmptyArray;
26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikimport java.lang.reflect.Array;
28b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikimport java.util.ArrayList;
29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikimport java.util.Arrays;
306f485569fa3d6047dcffd068aebf361e3598783cDerek Sollenbergerimport java.util.Collection;
31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikimport java.util.Collections;
32b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikimport java.util.List;
33b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikimport java.util.Objects;
34003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik
35b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/**
36b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * ArrayUtils contains some methods that you can call to find out
37b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * the most efficient increments by which to grow arrays.
386f485569fa3d6047dcffd068aebf361e3598783cDerek Sollenberger */
39003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craikpublic class ArrayUtils {
40b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    private static final int CACHE_SIZE = 73;
41003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    private static Object[] sCache = new Object[CACHE_SIZE];
42b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
43e4db79de127cfe961195f52907af8451026eaa20Chris Craik    private ArrayUtils() { /* cannot be instantiated */ }
44b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
45161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    public static byte[] newUnpaddedByteArray(int minLen) {
46b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return (byte[])VMRuntime.getRuntime().newUnpaddedArray(byte.class, minLen);
47b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
48b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
49003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    public static char[] newUnpaddedCharArray(int minLen) {
50b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        return (char[])VMRuntime.getRuntime().newUnpaddedArray(char.class, minLen);
51b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
52b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
53b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static int[] newUnpaddedIntArray(int minLen) {
54003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        return (int[])VMRuntime.getRuntime().newUnpaddedArray(int.class, minLen);
55003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    }
56b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
57003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    public static boolean[] newUnpaddedBooleanArray(int minLen) {
58b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return (boolean[])VMRuntime.getRuntime().newUnpaddedArray(boolean.class, minLen);
59b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
60b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
61003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    public static long[] newUnpaddedLongArray(int minLen) {
62b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return (long[])VMRuntime.getRuntime().newUnpaddedArray(long.class, minLen);
63b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
64b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
65b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static float[] newUnpaddedFloatArray(int minLen) {
66b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return (float[])VMRuntime.getRuntime().newUnpaddedArray(float.class, minLen);
67b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
68b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
69b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static Object[] newUnpaddedObjectArray(int minLen) {
70b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return (Object[])VMRuntime.getRuntime().newUnpaddedArray(Object.class, minLen);
71b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
72b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
73b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    @SuppressWarnings("unchecked")
74b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static <T> T[] newUnpaddedArray(Class<T> clazz, int minLen) {
75b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return (T[])VMRuntime.getRuntime().newUnpaddedArray(clazz, minLen);
76b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
77b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    /**
796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik     * Checks if the beginnings of two byte arrays are equal.
806fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik     *
816fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik     * @param array1 the first byte array
826fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik     * @param array2 the second byte array
836fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik     * @param length the number of bytes to check
846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik     * @return true if they're equal, false otherwise
856fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik     */
867df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    public static boolean equals(byte[] array1, byte[] array2, int length) {
87b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        if (length < 0) {
887df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck            throw new IllegalArgumentException();
896fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        }
906fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
916fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        if (array1 == array2) {
926fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            return true;
93b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
94b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (array1 == null || array2 == null || array1.length < length || array2.length < length) {
95b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return false;
96eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        }
97b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (int i = 0; i < length; i++) {
98b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (array1[i] != array2[i]) {
99b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                return false;
100b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            }
101b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
102b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return true;
103b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
104b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
105b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    /**
106b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * Returns an empty array of the specified type.  The intent is that
107b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * it will return the same empty array every time to avoid reallocation,
108b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     * although this is not guaranteed.
109eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita     */
1106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    @SuppressWarnings("unchecked")
111eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    public static <T> T[] emptyArray(Class<T> kind) {
112eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        if (kind == Object.class) {
1136fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            return (T[]) EmptyArray.OBJECT;
1146fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        }
1156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        int bucket = (kind.hashCode() & 0x7FFFFFFF) % CACHE_SIZE;
1176fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        Object cache = sCache[bucket];
1186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1196fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        if (cache == null || cache.getClass().getComponentType() != kind) {
120b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            cache = Array.newInstance(kind, 0);
1216fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            sCache[bucket] = cache;
1226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
123b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            // Log.e("cache", "new empty " + kind.getName() + " at " + bucket);
1246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        }
1256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
126b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        return (T[]) cache;
127b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    }
128b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
129b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    /**
130b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     * Checks if given array is null or has zero elements.
131b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     */
132eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    public static boolean isEmpty(@Nullable Collection<?> array) {
133b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        return array == null || array.isEmpty();
1346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
1356fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    /**
137b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     * Checks if given array is null or has zero elements.
1386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik     */
1396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    public static <T> boolean isEmpty(@Nullable T[] array) {
1406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        return array == null || array.length == 0;
1416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
1426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    /**
144b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     * Checks if given array is null or has zero elements.
1456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik     */
1466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    public static boolean isEmpty(@Nullable int[] array) {
1476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        return array == null || array.length == 0;
1486fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
149b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
150b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    /**
1516fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik     * Checks if given array is null or has zero elements.
152b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     */
153b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    public static boolean isEmpty(@Nullable long[] array) {
154b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        return array == null || array.length == 0;
1556fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
1566fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1576fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    /**
158b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     * Checks if given array is null or has zero elements.
159b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     */
160b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    public static boolean isEmpty(@Nullable byte[] array) {
161b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        return array == null || array.length == 0;
162b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    }
163b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
164b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    /**
165b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     * Checks if given array is null or has zero elements.
166b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     */
167b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    public static boolean isEmpty(@Nullable boolean[] array) {
168b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        return array == null || array.length == 0;
169b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    }
1707df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck
171b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    /**
172b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     * Length of the given array or 0 if it's null.
173b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     */
174b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    public static int size(@Nullable Object[] array) {
175b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        return array == null ? 0 : array.length;
176b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    }
177b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
1787df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    /**
179b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     * Checks that value is present as at least one of the elements of the array.
180b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     * @param array the array to check in
181b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     * @param value the value to check for
182b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     * @return true if the value is present in the array
183b87eadda1818034ce03d85f30388384d1ac65916Chris Craik     */
1846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    public static <T> boolean contains(@Nullable T[] array, T value) {
1856fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        return indexOf(array, value) != -1;
186b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
187b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
188b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    /**
189b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * Return first index of {@code value} in {@code array}, or {@code -1} if
190b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * not found.
191b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     */
192b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static <T> int indexOf(@Nullable T[] array, T value) {
193b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (array == null) return -1;
194b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (int i = 0; i < array.length; i++) {
195b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (Objects.equals(array[i], value)) return i;
196b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
197b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return -1;
198b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    /**
201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * Test if all {@code check} items are contained in {@code array}.
202b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     */
203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static <T> boolean containsAll(@Nullable T[] array, T[] check) {
204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (check == null) return true;
205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (T checkItem : check) {
206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (!contains(array, checkItem)) {
207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                return false;
208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            }
209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
210b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return true;
211b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
212b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
213e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik    /**
214b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * Test if any {@code check} items are contained in {@code array}.
215b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     */
216b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static <T> boolean containsAny(@Nullable T[] array, T[] check) {
217b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (check == null) return false;
218b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (T checkItem : check) {
219b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (contains(array, checkItem)) {
220b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                return true;
221b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            }
222b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
223b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return false;
224b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
225b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
226b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static boolean contains(@Nullable int[] array, int value) {
227b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (array == null) return false;
228b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (int element : array) {
229b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (element == value) {
230b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                return true;
231b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            }
232b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
233b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return false;
234b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
235b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
236b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static boolean contains(@Nullable long[] array, long value) {
237b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (array == null) return false;
238b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (long element : array) {
239b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (element == value) {
240b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                return true;
241b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            }
242b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
243b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return false;
2444c3980b6e43cc7c0541f54b8e7e2d9d6108be622Chris Craik    }
2454c3980b6e43cc7c0541f54b8e7e2d9d6108be622Chris Craik
2464c3980b6e43cc7c0541f54b8e7e2d9d6108be622Chris Craik    public static boolean contains(@Nullable char[] array, char value) {
2474c3980b6e43cc7c0541f54b8e7e2d9d6108be622Chris Craik        if (array == null) return false;
248b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (char element : array) {
249b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (element == value) {
250386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik                return true;
251386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik            }
252386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        }
253386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        return false;
254386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    }
255386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik
256386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    /**
257386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik     * Test if all {@code check} items are contained in {@code array}.
258b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     */
259386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    public static <T> boolean containsAll(@Nullable char[] array, char[] check) {
260386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        if (check == null) return true;
261386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        for (char checkItem : check) {
262386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik            if (!contains(array, checkItem)) {
2637df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck                return false;
264386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik            }
265386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        }
266e4db79de127cfe961195f52907af8451026eaa20Chris Craik        return true;
267386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    }
268b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
269a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    public static long total(@Nullable long[] array) {
270a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        long total = 0;
271a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        if (array != null) {
272a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            for (long value : array) {
273a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik                total += value;
2747df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck            }
275386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        }
276a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        return total;
277e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
278a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
279b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static int[] convertToIntArray(List<Integer> list) {
280a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        int[] array = new int[list.size()];
281b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (int i = 0; i < list.size(); i++) {
2827df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck            array[i] = list.get(i);
283b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
284b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return array;
285e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
286b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
287b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    /**
288b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * Adds value to given array if not already present, providing set-like
289b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * behavior.
290b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     */
291b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    @SuppressWarnings("unchecked")
2927a89600bac7ab889a5ba8a994c57d677de0e45d5Chris Craik    public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) {
293b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return appendElement(kind, array, element, false);
294b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
295b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
296b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    /**
297b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * Adds value to given array.
298b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     */
299b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    @SuppressWarnings("unchecked")
300b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element,
301b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            boolean allowDuplicates) {
302b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        final T[] result;
303b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        final int end;
304b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (array != null) {
305b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (!allowDuplicates && contains(array, element)) return array;
306b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            end = array.length;
307b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            result = (T[])Array.newInstance(kind, end + 1);
308b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            System.arraycopy(array, 0, result, 0, end);
309b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        } else {
310b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            end = 0;
311b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            result = (T[])Array.newInstance(kind, 1);
312b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
313b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        result[end] = element;
314b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return result;
3157df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    }
316b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
317b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    /**
318e4db79de127cfe961195f52907af8451026eaa20Chris Craik     * Removes value from given array if present, providing set-like behavior.
319b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     */
320b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    @SuppressWarnings("unchecked")
321b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static @Nullable <T> T[] removeElement(Class<T> kind, @Nullable T[] array, T element) {
322b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (array != null) {
323b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (!contains(array, element)) return array;
324b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            final int length = array.length;
325b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            for (int i = 0; i < length; i++) {
326b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                if (Objects.equals(array[i], element)) {
327b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                    if (length == 1) {
328b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                        return null;
329b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                    }
330b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                    T[] result = (T[])Array.newInstance(kind, length - 1);
331b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                    System.arraycopy(array, 0, result, 0, i);
332b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                    System.arraycopy(array, i + 1, result, i, length - i - 1);
333b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                    return result;
334b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                }
335b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            }
336b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
337b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return array;
338b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
339b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
340b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    /**
341b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * Adds value to given array.
342b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     */
343b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static @NonNull int[] appendInt(@Nullable int[] cur, int val,
344b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            boolean allowDuplicates) {
345b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (cur == null) {
346b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return new int[] { val };
347b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
348b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        final int N = cur.length;
3492dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik        if (!allowDuplicates) {
3502dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik            for (int i = 0; i < N; i++) {
3512dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik                if (cur[i] == val) {
3522dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik                    return cur;
3532dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik                }
3542dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik            }
3552dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik        }
3562dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik        int[] ret = new int[N + 1];
3572dbb4c46ee648c64bb977b6839374d73b5a605d9Chris Craik        System.arraycopy(cur, 0, ret, 0, N);
358b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        ret[N] = val;
359386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        return ret;
360268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    }
361268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik
362268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    /**
363268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik     * Adds value to given array if not already present, providing set-like
364268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik     * behavior.
365268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik     */
366268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    public static @NonNull int[] appendInt(@Nullable int[] cur, int val) {
367268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        return appendInt(cur, val, false);
368268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    }
369268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik
370268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    /**
371268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik     * Removes value from given array if present, providing set-like behavior.
372268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik     */
3737df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    public static @Nullable int[] removeInt(@Nullable int[] cur, int val) {
374268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        if (cur == null) {
375e4db79de127cfe961195f52907af8451026eaa20Chris Craik            return null;
376268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        }
377268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        final int N = cur.length;
378268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        for (int i = 0; i < N; i++) {
379268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik            if (cur[i] == val) {
380268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik                int[] ret = new int[N - 1];
381b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                if (i > 0) {
382268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik                    System.arraycopy(cur, 0, ret, 0, i);
383386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik                }
384386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik                if (i < (N - 1)) {
385b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                    System.arraycopy(cur, i + 1, ret, i, N - i - 1);
386386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik                }
387268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik                return ret;
388268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik            }
389268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        }
390268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        return cur;
391268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    }
392268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik
393268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    /**
394268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik     * Removes value from given array if present, providing set-like behavior.
3957df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck     */
396268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik    public static @Nullable String[] removeString(@Nullable String[] cur, String val) {
397e4db79de127cfe961195f52907af8451026eaa20Chris Craik        if (cur == null) {
398268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik            return null;
399268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        }
400268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        final int N = cur.length;
401268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik        for (int i = 0; i < N; i++) {
402b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (Objects.equals(cur[i], val)) {
4037df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck                String[] ret = new String[N - 1];
404386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik                if (i > 0) {
405386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik                    System.arraycopy(cur, 0, ret, 0, i);
406e4db79de127cfe961195f52907af8451026eaa20Chris Craik                }
407386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik                if (i < (N - 1)) {
408b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                    System.arraycopy(cur, i + 1, ret, i, N - i - 1);
409386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik                }
410b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                return ret;
411386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik            }
412caa24184735a607e87077c73262a42acdea7b8fbChris Craik        }
413caa24184735a607e87077c73262a42acdea7b8fbChris Craik        return cur;
414caa24184735a607e87077c73262a42acdea7b8fbChris Craik    }
415caa24184735a607e87077c73262a42acdea7b8fbChris Craik
416caa24184735a607e87077c73262a42acdea7b8fbChris Craik    /**
417caa24184735a607e87077c73262a42acdea7b8fbChris Craik     * Adds value to given array if not already present, providing set-like
418caa24184735a607e87077c73262a42acdea7b8fbChris Craik     * behavior.
419caa24184735a607e87077c73262a42acdea7b8fbChris Craik     */
420caa24184735a607e87077c73262a42acdea7b8fbChris Craik    public static @NonNull long[] appendLong(@Nullable long[] cur, long val) {
421caa24184735a607e87077c73262a42acdea7b8fbChris Craik        if (cur == null) {
422b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return new long[] { val };
423386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        }
424b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        final int N = cur.length;
4257df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck        for (int i = 0; i < N; i++) {
426386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik            if (cur[i] == val) {
427386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik                return cur;
428e4db79de127cfe961195f52907af8451026eaa20Chris Craik            }
429386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        }
430b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        long[] ret = new long[N + 1];
431b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        System.arraycopy(cur, 0, ret, 0, N);
432766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        ret[N] = val;
433766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        return ret;
4347df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    }
435766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
436766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    /**
437766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu     * Removes value from given array if present, providing set-like behavior.
438766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu     */
439766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    public static @Nullable long[] removeLong(@Nullable long[] cur, long val) {
440766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu        if (cur == null) {
441b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return null;
442b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
443eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        final int N = cur.length;
444b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (int i = 0; i < N; i++) {
445b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (cur[i] == val) {
446b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                long[] ret = new long[N - 1];
447b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                if (i > 0) {
448b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                    System.arraycopy(cur, 0, ret, 0, i);
449b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                }
450b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                if (i < (N - 1)) {
451b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                    System.arraycopy(cur, i + 1, ret, i, N - i - 1);
452b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                }
453b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                return ret;
454b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            }
455b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
456b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return cur;
457b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
458b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
459b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static @Nullable long[] cloneOrNull(@Nullable long[] array) {
460b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return (array != null) ? array.clone() : null;
461b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
462b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
463b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static @Nullable <T> ArraySet<T> cloneOrNull(@Nullable ArraySet<T> array) {
464eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        return (array != null) ? new ArraySet<T>(array) : null;
465b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
466b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
467b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static @NonNull <T> ArraySet<T> add(@Nullable ArraySet<T> cur, T val) {
468b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (cur == null) {
469b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            cur = new ArraySet<>();
470386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik        }
471b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        cur.add(val);
472b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return cur;
473b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
474b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
475b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static @Nullable <T> ArraySet<T> remove(@Nullable ArraySet<T> cur, T val) {
476b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (cur == null) {
477b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return null;
478b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
479b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        cur.remove(val);
480eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        if (cur.isEmpty()) {
481b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return null;
482b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        } else {
483b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return cur;
484b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
4857df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    }
486f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik
487f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik    public static @NonNull <T> ArrayList<T> add(@Nullable ArrayList<T> cur, T val) {
488e4db79de127cfe961195f52907af8451026eaa20Chris Craik        if (cur == null) {
489f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik            cur = new ArrayList<>();
490f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik        }
491b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        cur.add(val);
492b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return cur;
493386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    }
494b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
495b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static @Nullable <T> ArrayList<T> remove(@Nullable ArrayList<T> cur, T val) {
496f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik        if (cur == null) {
4977df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck            return null;
498f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik        }
499f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik        cur.remove(val);
500e4db79de127cfe961195f52907af8451026eaa20Chris Craik        if (cur.isEmpty()) {
501f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik            return null;
502f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik        } else {
503f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik            return cur;
504b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
505386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik    }
506f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik
507b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    public static <T> boolean contains(@Nullable Collection<T> cur, T val) {
508b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return (cur != null) ? cur.contains(val) : false;
5097df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    }
510f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik
511f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik    public static @Nullable <T> T[] trimToSize(@Nullable T[] array, int size) {
512e4db79de127cfe961195f52907af8451026eaa20Chris Craik        if (array == null || size == 0) {
513f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik            return null;
514b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        } else if (array.length == size) {
515b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            return array;
516b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        } else {
517a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            return Arrays.copyOf(array, size);
518b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
519b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
520a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
521a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    /**
522a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik     * Returns true if the two ArrayLists are equal with respect to the objects they contain.
523a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik     * The objects must be in the same order and be reference equal (== not .equals()).
52415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik     */
5257df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    public static <T> boolean referenceEquals(ArrayList<T> a, ArrayList<T> b) {
526a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        if (a == b) {
527a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            return true;
528e4db79de127cfe961195f52907af8451026eaa20Chris Craik        }
529a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
530a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        final int sizeA = a.size();
531b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        final int sizeB = b.size();
532a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        if (a == null || b == null || sizeA != sizeB) {
533d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            return false;
534b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
535d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik
536d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        boolean diff = false;
5377df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck        for (int i = 0; i < sizeA && !diff; i++) {
538d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            diff |= a.get(i) != b.get(i);
5394c3980b6e43cc7c0541f54b8e7e2d9d6108be622Chris Craik        }
540d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        return !diff;
541b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
542b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
543b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    /**
5447df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck     * Removes elements that match the predicate in an efficient way that alters the order of
5455430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik     * elements in the collection. This should only be used if order is not important.
546b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * @param collection The ArrayList from which to remove elements.
547e4db79de127cfe961195f52907af8451026eaa20Chris Craik     * @param predicate The predicate that each element is tested against.
548b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     * @return the number of elements removed.
549b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik     */
550e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik    public static <T> int unstableRemoveIf(@Nullable ArrayList<T> collection,
551b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                                           @NonNull java.util.function.Predicate<T> predicate) {
55254fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik        if (collection == null) {
5537df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck            return 0;
55454fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik        }
555b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
556e4db79de127cfe961195f52907af8451026eaa20Chris Craik        final int size = collection.size();
557b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        int leftIdx = 0;
558b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        int rightIdx = size - 1;
5591367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik        while (leftIdx <= rightIdx) {
5601367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik            // Find the next element to remove moving left to right.
561b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            while (leftIdx < size && !predicate.test(collection.get(leftIdx))) {
5621367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik                leftIdx++;
5631367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik            }
5641367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik
565b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            // Find the next element to keep moving right to left.
5661367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik            while (rightIdx > leftIdx && predicate.test(collection.get(rightIdx))) {
5671367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik                rightIdx--;
5681367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik            }
5691367d2550ebce40f45b16dc651bc3d8d22930801Chris Craik
570b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (leftIdx >= rightIdx) {
571b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                // Done.
572b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                break;
573d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            }
574d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
575d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            Collections.swap(collection, leftIdx, rightIdx);
576d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            leftIdx++;
577d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            rightIdx--;
578d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        }
579d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
580d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        // leftIdx is now at the end.
5817df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck        for (int i = size - 1; i >= leftIdx; i--) {
582d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            collection.remove(i);
583d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        }
584e4db79de127cfe961195f52907af8451026eaa20Chris Craik        return size - leftIdx;
585d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    }
586d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik}
587d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik