Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c072e6f authored by Al Sutton's avatar Al Sutton
Browse files

Support varargs for concatElements

concatElements currently can only support two arrays, this CL changes
it to use varargs so we can make use of it in an upcomming change which
needs a three way merge.

I've replaced the two way method with the varargs version, but I'm open
to discussion around keeping them both if the optimisations we can do
for a two way merge are seen as more valuable than the space saving from
having only one concatElements method.

Bug: 28437818
Test: atest ArrayUtilsTest
Change-Id: I634d279ceef7cd620efaf5a2c566e3ebadf6738e
parent f128bcc4
Loading
Loading
Loading
Loading
+52 −12
Original line number Diff line number Diff line
@@ -320,22 +320,62 @@ public class ArrayUtils {
        return array;
    }

    /**
     * Combine multiple arrays into a single array.
     *
     * @param kind The class of the array elements
     * @param arrays The arrays to combine
     * @param <T> The class of the array elements (inferred from kind).
     * @return A single array containing all the elements of the parameter arrays.
     */
    @SuppressWarnings("unchecked")
    public static @NonNull <T> T[] concatElements(Class<T> kind, @Nullable T[] a, @Nullable T[] b) {
        final int an = (a != null) ? a.length : 0;
        final int bn = (b != null) ? b.length : 0;
        if (an == 0 && bn == 0) {
    public static @NonNull <T> T[] concatElements(Class<T> kind, @Nullable T[]... arrays) {
        if (arrays == null || arrays.length == 0) {
            return createEmptyArray(kind);
        }

        int totalLength = 0;
        int maxLength = 0;
        T[] maxLengthArray = arrays[0];
        for (T[] item : arrays) {
            if (item == null) {
                continue;
            }

            totalLength += item.length;
            if (item.length > maxLength) {
                maxLengthArray = item;
                maxLength = item.length;
            }
        }

        // Optimization for entirely empty arrays.
        if (totalLength == 0) {
            return createEmptyArray(kind);
        }

        final T[] all = (T[]) Array.newInstance(kind, totalLength);
        int pos = 0;
        for (T[] item : arrays) {
            if (item == null || item.length == 0) {
                continue;
            }
            System.arraycopy(item, 0, all, pos, item.length);
            pos += item.length;
        }
        return all;
    }

    private static @NonNull <T> T[] createEmptyArray(Class<T> kind) {
        if (kind == String.class) {
            return (T[]) EmptyArray.STRING;
        } else if (kind == Object.class) {
            return (T[]) EmptyArray.OBJECT;
        }

        return (T[]) Array.newInstance(kind, 0);
    }
        final T[] res = (T[]) Array.newInstance(kind, an + bn);
        if (an > 0) System.arraycopy(a, 0, res, 0, an);
        if (bn > 0) System.arraycopy(b, 0, res, an, bn);
        return res;
    }


    /**
     * Adds value to given array if not already present, providing set-like
+36 −0
Original line number Diff line number Diff line
@@ -177,4 +177,40 @@ public class ArrayUtilsTest extends TestCase {
        assertArrayEquals(new Long[] { 1L, 2L, 3L, 4L },
                concatElements(Long.class, new Long[] { 1L, 2L }, new Long[] { 3L, 4L }));
    }

    public void testConcatElements_threeWay() {
        String[] array1 = { "1", "2" };
        String[] array2 = { "3", "4" };
        String[] array3 = { "5", "6" };
        String[] expectation = {"1", "2", "3", "4", "5", "6"};

        String[] concatResult = ArrayUtils.concatElements(String.class, array1, array2, array3);
        assertArrayEquals(expectation, concatResult);
    }


    public void testConcatElements_threeWayWithNull() {
        String[] array1 = { "1", "2" };
        String[] array2 = null;
        String[] array3 = { "5", "6" };
        String[] expectation = {"1", "2", "5", "6"};

        String[] concatResult = ArrayUtils.concatElements(String.class, array1, array2, array3);
        assertArrayEquals(expectation, concatResult);
    }

    public void testConcatElements_zeroElements() {
        String[] expectation = new String[0];

        String[] concatResult = ArrayUtils.concatElements(String.class);
        assertArrayEquals(expectation, concatResult);
    }

    public void testConcatElements_oneNullElement() {
        String[] expectation = new String[0];

        String[] concatResult = ArrayUtils.concatElements(String.class, null);
        assertArrayEquals(expectation, concatResult);
    }

}