Arrays类的分析及使用

1.  Arrays类介绍

Arrays类是Java API中提供的类,在java.util包中,此类包含用来操作数组的各种方法,比如排序和搜索,在这个类中如果指定数组引用为null,则此类方法都会抛出NullPointerException,此类还包含一个允许将数组作为列表来查看的静态工厂。

Arrays类包含sort,binarySearch,equals,fill,copyOf,asList,hashCode,deepHashCode,deepEquals,toString和deepToString public方法供其他类使用。其中从java.lang.Object继承的方法有clone,equals,finalize,getClass hashCode,notify,notifyAll,toString,wait。sort方法用来排序,binarySearch方法是二分查找,equals方法是用来比较,fill方法用来将某个特定的值填充到数组中,copyOf复制特定长度的数组,asList方法的作用是将数组作为列表来查看。

Arrays类包含两个私有类,分别是LegacyMergeSort类和ArrayList类,gacMergeSort是老版本的归并排序实现,而ArrayList是一个数组队列,用于实现asList方法。

Arrays的构造函数

private Arrays() {}

可以看到Arrays的构造函数被被设置为private的,表明这个类禁止使用默认构造函数并且不能被实例化,但是可以通过提供静态方法来使用这个类,这种模式就是单例模式。

Arrays方法摘要

public static void sort(Object[] a)
public static void sort(Object[] a, int fromIndex, int toIndex)
public static <T> void sort(T[] a, Comparator<? super T> c)
public static <T> void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c)

public static int binarySearch(Object[] a, Object key)
public static int binarySearch(Object[] a, int fromIndex, int toIndex, Object key)
public static <T> int binarySearch(T[] a, T key, Comparator<? super T> c)
public static <T> int binarySearch(T[] a, int fromIndex, int toIndex, T key, Comparator<? super T> c)

public static boolean equals(Object[] a, Object[] a2)

public static void fill(Object[] a, Object val)
public static void fill(Object[] a, int fromIndex, int toIndex, Object val)
public static <T> T[] copyOf(T[] original, int newLength)
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType)

public static <T> T[] copyOfRange(T[] original, int from, int to)
public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType)

public static <T> List<T> asList(T... a)

public static int hashCode(Object a[])

public static int deepHashCode(Object a[])

public static boolean deepEquals(Object[] a1, Object[] a2)

public static String toString(Object[] a)

public static String deepToString(Object[] a)

2.  Arrays类源码分析

依据JDK1.7.0_45的源码对Arrays类中的主要方法进行分析。

public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a);
    }

此方法表示根据元素的自然顺序对指定对象数组按升序进行排序,当用户没有请求使用老版本的归并排序时,直接使用ComparableTimSort类的方法实现,关于ComparableTimSort类之后会单独进行分析。

public static void sort(Object[] a, int fromIndex, int toIndex) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, fromIndex, toIndex);
        else
            ComparableTimSort.sort(a, fromIndex, toIndex);
    }

此方法表示的是根据元素的自然顺序对指定对象数组的指定范围按升序进行排序,其他实现与上面的额排序方法相同。

public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, c);
        else
            TimSort.sort(a, c);
    }

此方法表示根据指定比较器产生的顺序对指定对象数组进行排序。具体的排序实现是调用了TimSort的sort方法实现。

public static <T> void sort(T[] a, int fromIndex, int toIndex,
                                Comparator<? super T> c) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, fromIndex, toIndex, c);
        else
            TimSort.sort(a, fromIndex, toIndex, c);
    }

此方法表示根据指定比较器产生的顺序对指定对象数组的指定范围进行排序。同上具体的排序实现是调用了TimSort的sort方法实现。TimSort类在之后会单独分析。

public static int binarySearch(Object[] a, Object key) {
        return binarySearch0(a, 0, a.length, key);
}

// Like public version, but without range checks.
    private static int binarySearch0(Object[] a, int fromIndex, int toIndex,
                                     Object key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            Comparable midVal = (Comparable)a[mid];
            int cmp = midVal.compareTo(key);

            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

此方法表示使用二分搜索法来搜索指定数组,以获得指定对象,二分查找的具体实现没有进行范围检查。

public static int binarySearch(Object[] a, int fromIndex, int toIndex,
                                   Object key) {
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key);
}

此方法表示使用二分搜索法来搜索指定数组的范围,以获得指定对象。

public static <T> int binarySearch(T[] a, T key, Comparator<? super T> c) {
        return binarySearch0(a, 0, a.length, key, c);
}

// Like public version, but without range checks.
    private static <T> int binarySearch0(T[] a, int fromIndex, int toIndex,
                                         T key, Comparator<? super T> c) {
        if (c == null) {
            return binarySearch0(a, fromIndex, toIndex, key);
        }
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            T midVal = a[mid];
            int cmp = c.compare(midVal, key);
            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

二分查找的的泛型实现,使用二分搜索法来搜索指定数组,以获得指定对象。

public static <T> int binarySearch(T[] a, int fromIndex, int toIndex,
                                       T key, Comparator<? super T> c) {
        rangeCheck(a.length, fromIndex, toIndex);
        return binarySearch0(a, fromIndex, toIndex, key, c);
    }

二分查找的泛型实现,使用二分搜索法来搜索指定数组的范围,以获得指定对象。

public static boolean equals(Object[] a, Object[] a2) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++) {
            Object o1 = a[i];
            Object o2 = a2[i];
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }

        return true;
    }

此方法为如果两个指定的 Objects 数组彼此相等,则返回 true。在具体的实现中如果两个Objects中有1个为null则返回false。

public static void fill(Object[] a, Object val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }

此方法表示将指定的 Object 引用分配给指定 Object 数组的每个元素。

public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
}

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

复制指定的数组,截取或用 null 填充(如有必要),以使副本具有指定的长度。这里注意对泛型的使用。,最终调用System.arraycopy函数进行复制操作。

public static <T> T[] copyOfRange(T[] original, int from, int to) {
        return copyOfRange(original, from, to, (Class<T[]>) original.getClass());
}

public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

将指定数组的指定范围复制到一个新数组。

@SafeVarargs
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    /**
     * @serial include
     */
    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            if (array==null)
                throw new NullPointerException();
            a = array;
        }

        public int size() {
            return a.length;
        }

        public Object[] toArray() {
            return a.clone();
        }

        public <T> T[] toArray(T[] a) {
            int size = size();
            if (a.length < size)
                return Arrays.copyOf(this.a, size,
                                     (Class<? extends T[]>) a.getClass());
            System.arraycopy(this.a, 0, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }

        public E get(int index) {
            return a[index];
        }

        public E set(int index, E element) {
            E oldValue = a[index];
            a[index] = element;
            return oldValue;
        }

        public int indexOf(Object o) {
            if (o==null) {
                for (int i=0; i<a.length; i++)
                    if (a[i]==null)
                        return i;
            } else {
                for (int i=0; i<a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }

        public boolean contains(Object o) {
            return indexOf(o) != -1;
        }
    }

返回一个受指定数组支持的固定大小的列表。@SafeVarargs注解抑制编译器警告的示例,只能用在参数长度可变的方法或构造方法上,且方法必须声明为static或final,否则会出现编译错误。一个方法使用@SafeVarargs注解的前提是,开发人员必须确保这个方法的实现中对泛型类型参数的处理不会引发类型安全问题。

public static int hashCode(Object a[]) {
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a)
            result = 31 * result + (element == null ? 0 : element.hashCode());

        return result;
    }

基于指定数组的内容返回哈希码。这个方法继承自java.lang.Object。

public static int deepHashCode(Object a[]) {
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a) {
            int elementHash = 0;
            if (element instanceof Object[])
                elementHash = deepHashCode((Object[]) element);
            else if (element instanceof byte[])
                elementHash = hashCode((byte[]) element);
            else if (element instanceof short[])
                elementHash = hashCode((short[]) element);
            else if (element instanceof int[])
                elementHash = hashCode((int[]) element);
            else if (element instanceof long[])
                elementHash = hashCode((long[]) element);
            else if (element instanceof char[])
                elementHash = hashCode((char[]) element);
            else if (element instanceof float[])
                elementHash = hashCode((float[]) element);
            else if (element instanceof double[])
                elementHash = hashCode((double[]) element);
            else if (element instanceof boolean[])
                elementHash = hashCode((boolean[]) element);
            else if (element != null)
                elementHash = element.hashCode();

            result = 31 * result + elementHash;
        }

        return result;
    }

基于指定数组的“深层内容”返回哈希码。

public static boolean deepEquals(Object[] a1, Object[] a2) {
        if (a1 == a2)
            return true;
        if (a1 == null || a2==null)
            return false;
        int length = a1.length;
        if (a2.length != length)
            return false;

        for (int i = 0; i < length; i++) {
            Object e1 = a1[i];
            Object e2 = a2[i];

            if (e1 == e2)
                continue;
            if (e1 == null)
                return false;

            // Figure out whether the two elements are equal
            boolean eq = deepEquals0(e1, e2);

            if (!eq)
                return false;
        }
        return true;
    }

如果两个指定数组彼此是深层相等 的,则返回 true

public static String toString(Object[] a) {
        if (a == null)
            return "null";

        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append(‘[‘);
        for (int i = 0; ; i++) {
            b.append(String.valueOf(a[i]));
            if (i == iMax)
                return b.append(‘]‘).toString();
            b.append(", ");
        }
    }

返回指定数组内容的字符串表示形式。

public static String deepToString(Object[] a) {
        if (a == null)
            return "null";

        int bufLen = 20 * a.length;
        if (a.length != 0 && bufLen <= 0)
            bufLen = Integer.MAX_VALUE;
        StringBuilder buf = new StringBuilder(bufLen);
        deepToString(a, buf, new HashSet<Object[]>());
        return buf.toString();
    }

返回指定数组“深层内容”的字符串表示形式。

3.  性能分析

......

4.  Arrays类的使用

......

时间: 2024-10-14 20:15:18

Arrays类的分析及使用的相关文章

Java之美[从菜鸟到高手演练]之Arrays类及其方法分析

作者:二青 个人站点:zhangerqing.cn    邮箱:[email protected]    微博:http://weibo.com/xtfggef 本章主要介绍一下 java.util.Arrays类的重点方法,包括怎么使用及实现原理.这是一个算法类,主要是辅助数组类实现一些排序.搜索等功能,同时也支持数组到List的转换.本章系Java之美[从菜鸟到高手演练]系列之Arrays类及其方法分析,如果有任何问题,欢迎通过上面任何一种方式与我联系! 排序 本文使用JDK1.8.0_25

7.Java集合-Arrays类实现原理及源码分析

Java集合---Arrays类源码解析 转自:http://www.cnblogs.com/ITtangtang/p/3948765.html 一.Arrays.sort()数组排序 Java Arrays中提供了对所有类型的排序.其中主要分为Primitive(8种基本类型)和Object两大类. 基本类型:采用调优的快速排序: 对象类型:采用改进的归并排序. 1.对于基本类型源码分析如下(以int[]为例): Java对Primitive(int,float等原型数据)数组采用快速排序,对

Arrays类及其方法分析

排序 Arrays.sort()方法,对于基本数据类型采用DualPivotQuicksort(多路快排)进行排序,对于引用类型的数组,采用MergeSort(归并排序)进行排序,下面我们分别来讲一下这两类排序算法. 对基本类型数组的排序 Java中的八种基本数据类型,除了boolean,其它七种都是可以且有需求进行排序的,如果一个数组是单一的基础类型,形如int[] data, long data[]都可以直接使用Arrays.sort()进行排序.对于所有可排序的基本类型,都是采用DualP

Arrays源码分析

package java.util; import java.lang.reflect.Array; import java.util.concurrent.ForkJoinPool; import java.util.function.BinaryOperator; import java.util.function.Consumer; import java.util.function.DoubleBinaryOperator; import java.util.function.IntBi

13-02 Java 数组高级算法,Arrays类

冒泡排序 冒泡排序原理 冒泡排序代码: package cn.itcast_01; /* * 数组排序之冒泡排序: * 相邻元素两两比较,大的往后放,第一次完毕,最大值出现在了最大索引处 */ public class ArrayDemo { public static void main(String[] args) { // 定义一个数组 int[] arr = { 24, 69, 80, 57, 13 }; System.out.println("排序前:"); printArr

《java入门第一季》之Arrays类前传(排序案例以二分查找注意的问题)

根据排序算法,可以解决一些小案例.举例如下: /* * 把字符串中的字符进行排序. * 举例:"dacgebf" * 结果:"abcdefg" * * 分析: * A:定义一个字符串 * B:把字符串转换为字符数组 * C:把字符数组进行排序 * D:把排序后的字符数组转成字符串 * E:输出最后的字符串 */ public class ArrayTest { public static void main(String[] args) { // 定义一个字符串 S

数组的三种方式总结、 多维数组的遍历及 Arrays类的常用方法总结

一.数组的三种方式总结 1.创建数组 Java语言使用new操作符来创建数组,语法如下: arrayRefVar = new dataType[arraySize]; 上面的语法语句做了两件事: 一.使用 dataType[arraySize] 创建了一个数组. 二.把新创建的数组的引用赋值给变量 arrayRefVar. 数组变量的声明,和创建数组可以用一条语句完成,如下所示: dataType[] arrayRefVar = new dataType[arraySize]; 另外,你还可以使

使用 Arrays 类操作 Java 中的数组

//导入Arrays类import java.util.Arrays;//使用Arrays必须导入此行,导入包public class lianxi11 { public static void main(String[] args) { // 定义一个字符串数组 String[] hobbys = { "sports", "game", "movie" }; // 使用Arrays类的sort()方法对数组进行排序 Arrays.sort(ho

java之Arrays类

1.Arrays类概述 针对数组进行操作的工具类. 提供了排序,查找等功能. 2.成员方法 public static String toString(int[] a) public static void sort(int[] a) public static int binarySearch(int[] a,int value) package com; import java.util.Arrays; /**  * Arrays类概述及常用方法  *  针对数组进行操作的工具类.  *