`
seandeng888
  • 浏览: 158192 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

软件项目开发之必备工具类ArrayUtils

阅读更多

        JAVA的强大之外在于它是开源的且有大量的JAVA开源项目。这些开源项目从基本的工具类到系统组件再到大型的框架,可以说是无所不包。对于一位优秀的开发人员,学会使用这些开源项目那是必须的,更重要的是了解它的内在逻辑。接下来要写的是apache的commons-lang开源项目的ArrayUtils工具类,这个类在平时的工作中使用的比较多,但是由于内在逻辑比较简单,只要仔细看都能看懂,所以就不做过多的解释,还是以代码为主。

/**

 * 专门针对原型数组及对象数组的操作类。

 */

public class ArrayUtils {

 

    /**

     * 不能修改的空对象数组。

     */

    public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];

    /**

     * 不能修改的空字符数组。

     */

    public static final char[] EMPTY_CHAR_ARRAY = new char[0];

    /**

     * 不能修改的空字符对象数组。

     */

    public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];

 

    /**

     * 当在一个列表或数组里找不到元素时返回的索引值。

     */

    public static final int INDEX_NOT_FOUND = -1;

 

    /**

     * 创建数组。

     */

    public static <T> T[] toArray(final T... items) {

        // 这是JDK6.0的新特性。

        return items;

    }

 

    // 数组克隆。

    public static <T> T[] clone(final T[] array) {

        // 添加了对NULL的处理。

        if (array == null) {

            return null;

        }

        return array.clone();

    }

 

    /**

     * null转换为空数组。

     * 这是一个防止程序出现空指针错误的方法,建议在使用数组前都调用一次该方法。

     */

    public static Object[] nullToEmpty(final Object[] array) {

        // 添加了对NULL的处理。

        if (array == null || array.length == 0) {

            return EMPTY_OBJECT_ARRAY;

        }

        return array;

    }

 

    /**

     * 根据给定的起始索引和结束索引生成一个新的数组。

     * 用法如下:

     * Date[] someDates = (Date[])ArrayUtils.subarray(allDates, 2, 5);

     */

    public static <T> T[] subarray(final T[] array, int startIndexInclusive, int endIndexExclusive) {

        if (array == null) {

            return null;

        }

        if (startIndexInclusive < 0) {

            startIndexInclusive = 0;

        }

        if (endIndexExclusive > array.length) {

            endIndexExclusive = array.length;

        }

        final int newSize = endIndexExclusive - startIndexInclusive;

        final Class<?> type = array.getClass().getComponentType();

        if (newSize <= 0) {

            @SuppressWarnings("unchecked") // OK, because array is of type T

            final T[] emptyArray = (T[]) Array.newInstance(type, 0);

            return emptyArray;

        }

        @SuppressWarnings("unchecked") // OK, because array is of type T

        final

        T[] subarray = (T[]) Array.newInstance(type, newSize);

        // 使用了JDK的System.arraycopy()方法。

        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);

        return subarray;

    }

    

    // 判断两个数组长度是否一样。

     * null数组的长度视为0。不支持多维度数组。

     */

    public static boolean isSameLength(final Object[] array1, final Object[] array2) {

        if ((array1 == null && array2 != null && array2.length > 0) ||

            (array2 == null && array1 != null && array1.length > 0) ||

            (array1 != null && array2 != null && array1.length != array2.length)) {

                return false;

        }

        return true;

    }

 

    /**

     * 获取指标数组的长度。null数组的长度为0.

     */

    public static int getLength(final Object array) {

        // 添加了对NULL的判断。

        if (array == null) {

            return 0;

        }

        return Array.getLength(array);

    }

 

    /**

     * 判断两个数组(不能为NULL)的类型是否一样。

     */

    public static boolean isSameType(final Object array1, final Object array2) {

        if (array1 == null || array2 == null) {

            throw new IllegalArgumentException("The Array must not be null");

        }

        return array1.getClass().getName().equals(array2.getClass().getName());

    }

 

    // 数组元素反转。

    /**

     * 反转给定数组的元素的顺序。

     */

    public static void reverse(final Object[] array) {

        if (array == null) {

            return;

        }

        reverse(array, 0, array.length);

    }

 

    /**

     * 反转给定数组中给定范围的元素顺序。

     */

    public static void reverse(final boolean[] array, final int startIndexInclusive, final int endIndexExclusive) {

        if (array == null) {

            return;

        }

        int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;

        int j = Math.min(array.length, endIndexExclusive) - 1;

        boolean tmp;

        while (j > i) {

            tmp = array[j];

            array[j] = array[i];

            array[i] = tmp;

            j--;

            i++;

        }

    }

 

    /**

     * 根据给定的对象来查找它在特定数组的索引位置。

     */

    public static int indexOf(final Object[] array, final Object objectToFind) {

        return indexOf(array, objectToFind, 0);

    }

 

    /**

     * 从给定的索引位置开始查找特定对象在特定数组中的索引位置。

     */

    public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {

        if (array == null) {

            return INDEX_NOT_FOUND;

        }

        if (startIndex < 0) {

            startIndex = 0;

        }

        if (objectToFind == null) {

            for (int i = startIndex; i < array.length; i++) {

                if (array[i] == null) {

                    return i;

                }

            }

        } else if (array.getClass().getComponentType().isInstance(objectToFind)) {

            for (int i = startIndex; i < array.length; i++) {

                if (objectToFind.equals(array[i])) {

                    return i;

                }

            }

        }

        return INDEX_NOT_FOUND;

    }

 

    /**

     * 根据给定的对象来查找它在特定数组中最后出现的索引位置。

     */

    public static int lastIndexOf(final Object[] array, final Object objectToFind) {

        return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);

    }

 

    /**

     * 从给定的索引位置开始查找特定对象在特定数组中最后出现的索引位置。

     */

    public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {

        if (array == null) {

            return INDEX_NOT_FOUND;

        }

        if (startIndex < 0) {

            return INDEX_NOT_FOUND;

        } else if (startIndex >= array.length) {

            startIndex = array.length - 1;

        }

        if (objectToFind == null) {

            for (int i = startIndex; i >= 0; i--) {

                if (array[i] == null) {

                    return i;

                }

            }

        } else if (array.getClass().getComponentType().isInstance(objectToFind)) {

            for (int i = startIndex; i >= 0; i--) {

                if (objectToFind.equals(array[i])) {

                    return i;

                }

            }

        }

        return INDEX_NOT_FOUND;

    }

 

    /**

     * 判断某个对象是否存在于特定的数组里。

     */

    public static boolean contains(final Object[] array, final Object objectToFind) {

        return indexOf(array, objectToFind) != INDEX_NOT_FOUND;

    }

 

    // 原型/对象的数组转换器。

     * 将对象数组转换成原型数组。

     */

    public static char[] toPrimitive(final Character[] array) {

        if (array == null) {

            return null;

        } else if (array.length == 0) {

            return EMPTY_CHAR_ARRAY;

        }

        final char[] result = new char[array.length];

        for (int i = 0; i < array.length; i++) {

            result[i] = array[i].charValue();

        }

        return result;

    }

 

    /**

     * 将对象数组转换成原型数组。对于NULL元素可以给定替换字符。

     */

    public static char[] toPrimitive(final Character[] array, final char valueForNull) {

        if (array == null) {

            return null;

        } else if (array.length == 0) {

            return EMPTY_CHAR_ARRAY;

        }

        final char[] result = new char[array.length];

        for (int i = 0; i < array.length; i++) {

            final Character b = array[i];

            result[i] = (b == null ? valueForNull : b.charValue());

        }

        return result;

    }

 

    /**

     * 将原型数组转换成对象数组。

     */

    public static Character[] toObject(final char[] array) {

        if (array == null) {

            return null;

        } else if (array.length == 0) {

            return EMPTY_CHARACTER_OBJECT_ARRAY;

        }

        final Character[] result = new Character[array.length];

        for (int i = 0; i < array.length; i++) {

            result[i] = Character.valueOf(array[i]);

        }

        return result;

     }

 

    /**

     * 判断一个对象数组是否为NULL或为空(不存在元素)。

     */

    public static boolean isEmpty(final Object[] array) {

        return array == null || array.length == 0;

    }

 

    /**

     * 判断一个数组是否不为NULL或不为空(存在元素)。

     */

     public static <T> boolean isNotEmpty(final T[] array) {

         return (array != null && array.length != 0);

     }

 

    /**

     * 合并给定数组的所有元素到一个新的数组。

     * 主要是使用了System.arraycopy()方法。

     */

    public static <T> T[] addAll(final T[] array1, final T... array2) {

        if (array1 == null) {

            return clone(array2);

        } else if (array2 == null) {

            return clone(array1);

        }

        final Class<?> type1 = array1.getClass().getComponentType();

        @SuppressWarnings("unchecked") // OK, because array is of type T

        final

        T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);

        System.arraycopy(array1, 0, joinedArray, 0, array1.length);

        try {

            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);

        } catch (final ArrayStoreException ase) {

            // Check if problem was due to incompatible types

            /*

             * We do this here, rather than before the copy because:

             * - it would be a wasted check most of the time

             * - safer, in case check turns out to be too strict

             */

            final Class<?> type2 = array2.getClass().getComponentType();

            if (!type1.isAssignableFrom(type2)){

                throw new IllegalArgumentException("Cannot store "+type2.getName()+" in an array of "

                        +type1.getName(), ase);

            }

            throw ase; // No, so rethrow original

        }

        return joinedArray;

    }

 

    /**

     * 拷贝给定的数组并添加给定元素到新数组的后面。

     */

    public static <T> T[] add(final T[] array, final T element) {

        Class<?> type;

        if (array != null){

            type = array.getClass();

        } else if (element != null) {

            type = element.getClass();

        } else {

            throw new IllegalArgumentException("Arguments cannot both be null");

        }

        @SuppressWarnings("unchecked") // type must be T

        final

        T[] newArray = (T[]) copyArrayGrow1(array, type);

        newArray[newArray.length - 1] = element;

        return newArray;

    }

 

    /**

     * 拷贝一个数组并将其长度加1。

     */

    private static Object copyArrayGrow1(final Object array, final Class<?> newArrayComponentType) {

        if (array != null) {

            final int arrayLength = Array.getLength(array);

            final Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);

            System.arraycopy(array, 0, newArray, 0, arrayLength);

            return newArray;

        }

        return Array.newInstance(newArrayComponentType, 1);

    }

    /**

     * 在给定的数组里,在给定的索引位置添加给定的元素。

     */

    public static boolean[] add(final boolean[] array, final int index, final boolean element) {

        return (boolean[]) add(array, index, Boolean.valueOf(element), Boolean.TYPE);

    }

 

    /**

     * 从给定的数组里删除给定索引位置的元素。

     */

    @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input

    public static <T> T[] remove(final T[] array, final int index) {

        return (T[]) remove((Object) array, index);

    }

 

    /**

     * 从给定的数组里删除第一次出现的给定的元素。

     */

    public static <T> T[] removeElement(final T[] array, final Object element) {

        final int index = indexOf(array, element);

        if (index == INDEX_NOT_FOUND) {

            return clone(array);

        }

        return remove(array, index);

    }

 

    /**

     * 从给定的数组里删除给定索引位置的元素。

     */

    private static Object remove(final Object array, final int index) {

        final int length = getLength(array);

        if (index < 0 || index >= length) {

            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);

        }

 

        final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);

        System.arraycopy(array, 0, result, 0, index);

        if (index < length - 1) {

            System.arraycopy(array, index + 1, result, index, length - index - 1);

        }

        return result;

    }

 

    /**

     * 从给定的数组里删除给定的多个索引位置的元素。

     */

    @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input

    public static <T> T[] removeAll(final T[] array, final int... indices) {

        return (T[]) removeAll((Object) array, clone(indices));

    }

 

    /**

     * 从给定的数组里删除给定的元素。

     */

    public static <T> T[] removeElements(final T[] array, final T... values) {

        if (isEmpty(array) || isEmpty(values)) {

            return clone(array);

        }

        final HashMap<T, MutableInt> occurrences = new HashMap<T, MutableInt>(values.length);

        for (final T v : values) {

            final MutableInt count = occurrences.get(v);

            if (count == null) {

                occurrences.put(v, new MutableInt(1));

            } else {

                count.increment();

            }

        }

        final BitSet toRemove = new BitSet();

        for (final Map.Entry<T, MutableInt> e : occurrences.entrySet()) {

            final T v = e.getKey();

            int found = 0;

            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {

                found = indexOf(array, v, found);

                if (found < 0) {

                    break;

                }

                toRemove.set(found++);

            }

        }

        @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input

        final

        T[] result = (T[]) removeAll(array, toRemove);

        return result;

    }

 

    /**

     * 根据给定的索引位置删除多个数组元素。

     */

    static Object removeAll(final Object array, final int... indices) {

        final int length = getLength(array);

        int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed

 

        if (isNotEmpty(indices)) {

            Arrays.sort(indices);

 

            int i = indices.length;

            int prevIndex = length;

            while (--i >= 0) {

                final int index = indices[i];

                if (index < 0 || index >= length) {

                    throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);

                }

                if (index >= prevIndex) {

                    continue;

                }

                diff++;

                prevIndex = index;

            }

        }

        final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);

        if (diff < length) {

            int end = length; // index just after last copy

            int dest = length - diff; // number of entries so far not copied

            for (int i = indices.length - 1; i >= 0; i--) {

                final int index = indices[i];

                if (end - index > 1) { // same as (cp > 0)

                    final int cp = end - index - 1;

                    dest -= cp;

                    System.arraycopy(array, index + 1, result, dest, cp);

                    // Afer this copy, we still have room for dest items.

                }

                end = index;

            }

            if (end > 0) {

                System.arraycopy(array, 0, result, 0, end);

            }

        }

        return result;

    }

}

2
1
分享到:
评论

相关推荐

    Commons项目中用来处理Java基本对象方法的工具类包,可以简化很多平时经常要用到的写法

    Apache Commons Lang是Apache软件基金会开发的一个Java库,它提供了一系列高度实用的工具类,用于处理常见的编程任务。这个库特别关注那些在Java的标准库`java.lang`中未涵盖或者可以进一步简化的方法。通过使用Lang...

    apche最全commons包搭建项目必备

    Apache Commons IO 提供了一系列与 I/O 相关的工具类,涵盖了文件、流、过滤器、读写、转换、字符集、系统属性等方面。例如: - `FileUtils` 类提供了一系列静态方法用于文件和目录的操作,如复制、移动、删除等。 ...

    commons-lang-1.0.1.tar.gz

    Apache Commons Lang 是一个由 Apache 软件基金会开发的 Java 类库,它提供了一系列实用工具类,用于增强Java语言的功能。这个"commons-lang-1.0.1.tar.gz"文件是一个压缩包,其中包含了Lang项目的1.0.1版本。在Java...

    jakarta commons cookbook.zip

    总之,《Jakarta Commons Cookbook》是Java开发者必备的参考书之一,它以实例的形式详细介绍了Jakarta Commons各个组件的使用,对于提升开发效率和代码质量具有重要的意义。如果你在实际工作中遇到与文件操作、对象...

    Apache Commons工具集

    Apache Commons是Java开发中不可或缺的一部分,它提供了一系列实用的工具类和组件,极大地丰富了Java标准库的功能。这个工具集包含了许多模块,每个模块都专注于特定的编程任务,旨在简化和优化开发流程。以下是一些...

    commons-lang所有版本(1.0-3.4).zip

    Apache Commons Lang 是一个由 Apache 软件基金会开发的 Java 类库,它是 Apache Commons 项目的一部分,专注于提供一些核心的、实用的、与语言相关的工具类。这个压缩包"commons-lang所有版本(1.0-3.4).zip"包含了...

    commons-lang3-3.9-tar-压缩包.zip

    Apache Commons Lang是Apache软件基金会开发的一个Java类库,它提供了许多在Java标准库中未包含的实用工具类。"commons-lang3-3.9-tar"是一个压缩包,包含了Lang项目版本3.9的源码和相关文件。这个库特别受欢迎,...

    commons-lang.jar,各种版本

    这个库通过其丰富的功能,帮助开发者编写出更加简洁、高效、可维护的代码,是Java开发者的必备工具之一。选择不同版本的`commons-lang.jar`主要是考虑兼容性和功能需求,新版本通常会修复已知问题并引入新的特性和...

    commos api

    这个API通常指的是Apache Commons项目中的API,这是一个由Apache软件基金会维护的开源项目,旨在为Java开发者提供实用工具类和库。Apache Commons包含了许多子项目,每个子项目专注于特定的编程任务,例如字符串处理...

    jar包-commons-lang-2.4.jar

    Commons Lang库的核心目标是解决Java标准类库中未涵盖的通用问题,它包含了一系列实用工具类,涵盖了字符串处理、日期时间操作、数学计算、反射、类型转换等多个领域。下面,我们将深入探讨这个库中的一些关键知识点...

    commons-lang3-3.7

    Apache Commons Lang是一个强大的Java工具库,它为Java开发人员提供了许多实用的功能,极大地增强了标准Java类库的能力。...其丰富的功能、良好的性能和广泛的社区支持,使其成为Java开发者的必备工具之一。

Global site tag (gtag.js) - Google Analytics