org.apache.geode.internal.util.ArrayUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.geode.internal.util.ArrayUtils.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.internal.util;

import org.apache.commons.lang.StringUtils;
import org.apache.geode.internal.offheap.annotations.Unretained;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *
 * Handle some simple editing of fixed-length arrays.
 *
 * TODO use Java 1.5 template classes to simplify this interface
 *
 */
public abstract class ArrayUtils {

    /**
     * Gets the element at index in the array in a bound-safe manner. If index is not a valid index in
     * the given array, then the default value is returned.
     * <p/>
     * 
     * @param <T> the class type of the elements in the array.
     * @param array the array from which the element at index is retrieved.
     * @param index the index into the array to retrieve the element.
     * @param defaultValue the default value of element type to return in the event that the array
     *        index is invalid.
     * @return the element at index from the array or the default value if the index is invalid.
     */
    public static <T> T getElementAtIndex(T[] array, int index, T defaultValue) {
        try {
            return array[index];
        } catch (ArrayIndexOutOfBoundsException ignore) {
            return defaultValue;
        }
    }

    /**
     * Gets the first element from the given array or null if the array reference is null or the array
     * length is 0.
     * <p/>
     * 
     * @param <T> the Class type of the elements in the array.
     * @param array the array of elements from which to retrieve the first element.
     * @return the first element from the array or null if either the array reference is null or the
     *         array length is 0.
     */
    public static <T> T getFirst(final T... array) {
        return (array != null && array.length > 0 ? array[0] : null);
    }

    /**
     * Converts the specified Object array into a String representation.
     * <p/>
     * 
     * @param array the Object array of elements to convert to a String.
     * @return a String representation of the Object array.
     * @see java.lang.StringBuilder
     */
    public static String toString(final Object... array) {
        final StringBuilder buffer = new StringBuilder("[");
        int count = 0;

        if (array != null) {
            for (final Object element : array) {
                buffer.append(count++ > 0 ? ", " : StringUtils.EMPTY).append(element);
            }
        }

        buffer.append("]");

        return buffer.toString();
    }

    public static String toString(final String... array) {
        return toString((Object[]) array);
    }

    /**
     * Insert an element into an array. The element is inserted at the given position, all elements
     * afterwards are moved to the right.
     *
     * @param originalArray array to insert into
     * @param pos position at which to insert the element
     * @param element element to add
     * @return the new array
     */
    public static Object[] insert(Object[] originalArray, int pos, Object element) {
        Object[] newArray = (Object[]) java.lang.reflect.Array
                .newInstance(originalArray.getClass().getComponentType(), originalArray.length + 1);

        // Test Cases (proof of correctness by examining corner cases)
        // 1) A B C D insert at 0: expect X A B C D
        // 2) A B C D insert at 2: expect A B X C D
        // 3) A B C D insert at 4: expect A B C D X

        // copy everything before the given position
        if (pos > 0) {
            System.arraycopy(originalArray, 0, newArray, 0, pos); // does not copy originalArray[pos],
                                                                  // where we insert
        }

        // 1) A B C D insert at 0: no change, ". . . . ."
        // 2) A B C D insert at 2: copy "A B", "A B . . ."
        // 3) A B C D insert at 4: copy "A B C D", "A B C D ."

        // insert
        newArray[pos] = element;

        // 1) A B C D insert at 0: "X . . . ."
        // 2) A B C D insert at 2: "A B X . ."
        // 3) A B C D insert at 4: "A B C D X" (all done)

        // copy remaining elements
        if (pos < originalArray.length) {
            System.arraycopy(originalArray, pos, // originalArray[pos] first element copied
                    newArray, pos + 1, // newArray[pos + 1] first destination
                    originalArray.length - pos); // number of elements left
        }

        // 1) A B C D insert at 0: "A B C D" copied at 1: "X A B C D"
        // 2) A B C D insert at 2: "C D" copied at 3: "A B X C D"
        // 3) A B C D insert at 4: no change
        return newArray;
    }

    /**
     * Remove element from an array. The element is removed at the specified position, and all
     * remaining elements are moved to the left.
     *
     * @param originalArray array to remove from
     * @param pos position to remove
     * @return the new array
     */
    public static Object[] remove(Object[] originalArray, int pos) {
        Object[] newArray = (Object[]) java.lang.reflect.Array
                .newInstance(originalArray.getClass().getComponentType(), originalArray.length - 1);

        // Test cases: (proof of correctness)
        // 1) A B C D E remove 0: expect "B C D E"
        // 2) A B C D E remove 2: expect "A B D E"
        // 3) A B C D E remove 4: expect "A B C D"

        // Copy everything before
        if (pos > 0) {
            System.arraycopy(originalArray, 0, newArray, 0, pos); // originalArray[pos - 1] is last
                                                                  // element copied
        }

        // 1) A B C D E remove 0: no change, ". . . ."
        // 2) A B C D E remove 2: "A B" copied at beginning: "A B . ."
        // 3) A B C D E remove 4: "A B C D" copied (all done)

        // Copy everything after
        if (pos < originalArray.length - 1) {
            System.arraycopy(originalArray, pos + 1, // originalArray[pos + 1] is first element copied
                    newArray, pos, // first position to copy into
                    originalArray.length - 1 - pos);
        }

        // 1) A B C D E remove 0: "B C D E" copied into to position 0
        // 2) A B C D E remove 2: "D E" copied into position 2: "A B D E"
        // 3) A B C D E remove 4: no change
        return newArray;
    }

    public static String objectRefString(Object obj) {
        return obj != null
                ? obj.getClass().getSimpleName() + '@' + Integer.toHexString(System.identityHashCode(obj))
                : "(null)";
    }

    public static void objectRefString(Object obj, StringBuilder sb) {
        if (obj != null) {
            sb.append(obj.getClass().getSimpleName()).append('@')
                    .append(Integer.toHexString(System.identityHashCode(obj)));
        } else {
            sb.append("(null)");
        }
    }

    /** Get proper string for an object including arrays. */
    public static String objectString(Object obj) {
        StringBuilder sb = new StringBuilder();
        objectString(obj, sb);
        return sb.toString();
    }

    /** Get proper string for an object including arrays. */
    public static void objectString(Object obj, StringBuilder sb) {
        if (obj instanceof Object[]) {
            sb.append('(');
            boolean first = true;
            for (Object o : (Object[]) obj) {
                if (!first) {
                    sb.append(',');
                } else {
                    first = false;
                }
                objectString(o, sb);
            }
            sb.append(')');
        } else {
            objectStringWithBytes(obj, sb);
        }
    }

    /**
     * Get proper string for an an object including arrays with upto one dimension of arrays.
     */
    public static String objectStringNonRecursive(@Unretained Object obj) {
        StringBuilder sb = new StringBuilder();
        objectStringNonRecursive(obj, sb);
        return sb.toString();
    }

    public static boolean areByteArrayArrayEquals(byte[][] v1, byte[][] v2) {
        boolean areEqual = false;
        if (v1.length == v2.length) {
            areEqual = true;
            for (int index = 0; index < v1.length; ++index) {
                if (!Arrays.equals(v1[index], v2[index])) {
                    areEqual = false;
                    break;
                }
            }
        }
        return areEqual;
    }

    /**
     * Get proper string for an an object including arrays with upto one dimension of arrays.
     */
    public static void objectStringNonRecursive(@Unretained Object obj, StringBuilder sb) {
        if (obj instanceof Object[]) {
            sb.append('(');
            boolean first = true;
            for (Object o : (Object[]) obj) {
                if (!first) {
                    sb.append(',');
                    sb.append(o);
                } else {
                    first = false;
                    // show the first byte[] for byte[][] storage
                    objectStringWithBytes(o, sb);
                }
            }
            sb.append(')');
        } else {
            objectStringWithBytes(obj, sb);
        }
    }

    private static void objectStringWithBytes(@Unretained Object obj, StringBuilder sb) {
        if (obj instanceof byte[]) {
            sb.append('(');
            boolean first = true;
            final byte[] bytes = (byte[]) obj;
            int numBytes = 0;
            for (byte b : bytes) {
                if (!first) {
                    sb.append(',');
                } else {
                    first = false;
                }
                sb.append(b);
                // terminate with ... for large number of bytes
                if (numBytes++ >= 5000 && numBytes < bytes.length) {
                    sb.append(" ...");
                    break;
                }
            }
            sb.append(')');
        } else {
            sb.append(obj);
        }
    }

    /**
     * Check if two objects, possibly null, are equal. Doesn't really belong to this class...
     */
    public static boolean objectEquals(Object o1, Object o2) {
        if (o1 == o2) {
            return true;
        }
        if (o1 == null) {
            return false;
        }
        return o1.equals(o2);
    }

    /**
     * Converts the primitive int array into an Integer wrapper object array.
     * </p>
     * 
     * @param array the primitive int array to convert into an Integer wrapper object array.
     * @return an Integer array containing the values from the elements in the primitive int array.
     */
    public static Integer[] toIntegerArray(final int[] array) {
        final Integer[] integerArray = new Integer[array == null ? 0 : array.length];

        if (array != null) {
            for (int index = 0; index < array.length; index++) {
                integerArray[index] = array[index];
            }
        }

        return integerArray;
    }

    /**
     * Converts a double byte array into a double Byte array.
     * 
     * @param array the double byte array to convert into double Byte array
     * @return a double array of Byte objects containing values from the double byte array
     */
    public static Byte[][] toByteArray(final byte[][] array) {
        if (array == null) {
            return null;
        }
        final Byte[][] byteArray = new Byte[array.length][];
        for (int i = 0; i < array.length; i++) {
            byteArray[i] = new Byte[array[i].length];
            for (int j = 0; j < array[i].length; j++) {
                byteArray[i][j] = array[i][j];
            }
        }
        return byteArray;
    }

    /**
     * Converts a double Byte array into a double byte array.
     * 
     * @param byteArray the double Byte array to convert into a double byte array
     * @return a double byte array containing byte values from the double Byte array
     */
    public static byte[][] toBytes(final Byte[][] byteArray) {
        if (byteArray == null) {
            return null;
        }
        final byte[][] array = new byte[byteArray.length][];
        for (int i = 0; i < byteArray.length; i++) {
            array[i] = new byte[byteArray[i].length];
            for (int j = 0; j < byteArray[i].length; j++) {
                array[i][j] = byteArray[i][j];
            }
        }
        return array;
    }

    /**
     * Use this instead of Arrays.asList(T... array) when you need a modifiable List.
     *
     * Returns a modifiable list containing the elements of the specified array.
     *
     * <p>
     * Example usage:
     * 
     * <pre>
     * List&lt;String&gt; stooges = Arrays.asList("Larry", "Moe", "Curly");
     * stooges.remove("Curly");
     * </pre>
     *
     * @param <T> the class of the objects in the array
     * @param array the array of elements to be added to the list
     * @return a list containing the elements of the specified array
     */
    public static <T> List<T> asList(T... array) {
        return new ArrayList<>(Arrays.asList(array));
    }

}