【Arrays类】java中Arrays类的详解

一、概述

这个类是我们以后开发中使用比较方便、频繁的一个工具类!

  • Arrays这个类包含用于操作数组的各种方法(例如排序和搜索)。 此类还包含一个静态工厂,允许将数组视为列表。
  • 如果指定的数组引用为null,则此类中的方法都抛出NullPointerException

二、常用方法

1. static List aList(T… a):返回由指定数组支持的固定大小的列表。

下面是aList的实现方法

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

其实,也就是通过ArrayList的构造方法来创建List!
  底层是通过传入数组类型的数组,来创建ArrayList
先通过Objects.requireNonNull(array);判断参数不是null,返回数组对象,赋值给ArrayList类的数组private final E[] a中

关于ArrayList类如下:

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) {
            a = Objects.requireNonNull(array);//判断传入参数是否为null,返回赋值给a
        }

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

        @Override
        public Object[] toArray() {
            return Arrays.copyOf(a, a.length, Object[].class);
        }
...
}
2. equals:比较两个数组是否相等
  • equals​(boolean[] a, boolean[] a2)
    如果两个指定的布尔数组彼此 相等 ,则返回 true
  • equals​(boolean[] a, int aFromIndex, int aToIndex, boolean[] b, int bFromIndex, int bToIndex)(范围值包含FromIndex,不包含ToIndex
    如果两个指定的布尔数组在指定范围内彼此 相等 ,则返回true。
  • equals​(T[] a, T[] a2, Comparator<? super T> cmp):按照指定比较器来判断是否相等
  • equals方法里参数类型还有其他
  • 底层是先比较地址值是否相等,然后比较是否为空,再然后比较长度是否不同,最后调用mismatch来查找第一个不匹配的位置,mismatch没有不匹配就返回-1,所以ArraysSupport.mismatch(a, a2, length) < 0,有不匹配就会大于0,<0就不成立,就返回false
  • 有范围的比较,开始先调用rangCheck检查范围是否合法,防止给定范围越界,就会抛出异常ArrayIndexOutOfBoundsException或者IllegalArgumentException,然后根据长度差来比较两个长度是否相同,最后调用mismatch来匹配返回结果。

底层源码如下:

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

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

        return ArraysSupport.mismatch(a, a2, length) < 0;
    }
public static boolean equals(int[] a, int aFromIndex, int aToIndex,
                                 int[] b, int bFromIndex, int bToIndex) {
        rangeCheck(a.length, aFromIndex, aToIndex);
        rangeCheck(b.length, bFromIndex, bToIndex);

        int aLength = aToIndex - aFromIndex;
        int bLength = bToIndex - bFromIndex;
        if (aLength != bLength)
            return false;

        return ArraysSupport.mismatch(a, aFromIndex,
                                      b, bFromIndex,
                                      aLength) < 0;
    }
 static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
        if (fromIndex > toIndex) {
            throw new IllegalArgumentException(
                    "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
        }
        if (fromIndex < 0) {
            throw new ArrayIndexOutOfBoundsException(fromIndex);
        }
        if (toIndex > arrayLength) {
            throw new ArrayIndexOutOfBoundsException(toIndex);
        }
    }
3. copyOf:复制数组副本
  • copyOf​(boolean[] original, int newLength)
    从0开始截取newLength长度复制到新数组中
  • copyOfRange​(boolean[] original, int from, int to)
    将指定范围内容复制到新数组中
  • 底层是先拿到数组的类型,然后调用copyOf重载的另一个方法,先判断类型去创建一个新数组copy,最后调用System.arraycopy方法来实现原数组跟新数组copy的复制。最后返回新数组copy

测试代码:

		String[] arr3 = {"a","bb","ds"};
        String[] arr4 = {"a","bc","dd"};
		//copyOf,copyOfRange
        String[] arr3Copy = Arrays.copyOf(arr3, 2);
        String[] arr4Copy = Arrays.copyOfRange(arr4, 0, 2);//包含前者不包含后者
        System.out.println(arr3Copy.length);//2
        System.out.println(Arrays.toString(arr3Copy));//[a, bb]
        System.out.println(arr4Copy.length);//2
        System.out.println(Arrays.toString(arr4Copy));//[a, bc]

源码:

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) {
        @SuppressWarnings("unchecked")
        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;
    }
4. sort:排序

parallelSort :功能类似sort,都是给数组升序排序!
排序算法是并行排序合并,它将数组分解为自身排序然后合并的子数组。 当子阵列长度达到最小粒度时,使用适当的Arrays.sort方法对子阵列进行排序。 如果指定数组的长度小于最小粒度,则使用适当的Arrays.sort方法对其进行排序。 该算法需要的工作空间不大于原始数组的大小。 ForkJoin common pool用于执行任何并行任务

  • sort(int[]a)
    对数组进行排序
  • sort​(byte[] a, int fromIndex, int toIndex)
    按升序对数组的指定范围进行排序。
  • sort​(T[] a, Comparator<? super T> c)
    根据指定比较器引发的顺序对指定的对象数组进行排序
  • 底层是:此类通过以下方式实现双枢轴快速排序算法:
    弗拉基米尔·雅罗斯拉夫斯基、乔恩·本特利和乔什·布洛赫算法
    在许多导致其他问题的数据集上提供O(n log(n))性能
    快速排序将降级为二次性能,通常是
    比传统(单轴)快速排序实现更快。

测试代码:

		int[] arr = {8,15,2,14,25,66,2,19};
        int[] arr2 = {21,2,23,11,4,22,19};
		//sort 升序排序
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));//[2, 2, 2, 2, 2, 2, 3, 3]
        Arrays.sort(arr2,0,4);//前四个数排序
        System.out.println(Arrays.toString(arr2));//[2, 11, 21, 23, 4, 22, 19]

        int[] arr5 = {1,25,12,16,8,22,15,33};
        Arrays.parallelSort(arr5);

底层代码:

public static void sort(int[] a) {
        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
    }
5. binarySearch:二分查找关键字
  • int binarySearch(int[] a,int key)
    对数组排序后,利用二分查找指定key值
  • binarySearch​(byte[] a, int fromIndex, int toIndex, byte key)
    使用二进制搜索算法搜索指定值的指定字节数组的范围
  • 底层通过数组长度加入参数中,调用binarySearch0来查找,binarySearch是标准的二分查找算法!

底层源码:

   public static int binarySearch(int[] a, int key) {
        return binarySearch0(a, 0, a.length, key);
    }
private static int binarySearch0(int[] a, int fromIndex, int toIndex,
                                     int key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            int midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }
6. fill:填充覆盖
  • fill​(boolean[] a, boolean val)
    将指定的布尔值分配给指定的布尔数组的每个元素。
  • fill​(boolean[] a, int fromIndex, int toIndex, boolean val)
    将指定的布尔值分配给指定的布尔数组的指定范围的每个元素。
  • 参数类型还有其他
  • 底层是 遍历数组每个元素,全部赋值为指定值
 public static void fill(int[] a, int val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
    }
7.compare​:比较大小
  • compare​(boolean[] a, boolean[] b)
    字典顺序去比较两个参数
  • compare​(double[] a, int aFromIndex, int aToIndex, double[] b, int bFromIndex, int bToIndex)
    指定范围做比较
  • compare​(T[] a, T[] b, Comparator<? super T> cmp)
    按照指定比较器来比较两个数组大小

源码:

public static <T extends Comparable<? super T>> int compare(T[] a, T[] b) {
        if (a == b)
            return 0;
        // A null array is less than a non-null array
        if (a == null || b == null)
            return a == null ? -1 : 1;

        int length = Math.min(a.length, b.length);
        for (int i = 0; i < length; i++) {
            T oa = a[i];
            T ob = b[i];
            if (oa != ob) {
                // A null element is less than a non-null element
                if (oa == null || ob == null)
                    return oa == null ? -1 : 1;
                int v = oa.compareTo(ob);
                if (v != 0) {
                    return v;
                }
            }
        }

        return a.length - b.length;
    }
8.mismatch​:查找第一个不匹配位置
  • mismatch​(boolean[] a, boolean[] b)
    查找并返回两个 boolean数组之间第一个不匹配的索引,否则如果未找到不匹配则返回-1。
  • mismatch​(boolean[] a, int aFromIndex, int aToIndex, boolean[] b, int bFromIndex, int bToIndex)
    查找并返回指定范围内两个 boolean数组之间第一个不匹配的相对索引,否则返回-1(如果未找到不匹配)。
  • 参数类型还有其他
9.toString

输出数组信息
底层遍历数组,用StringBuilder来拼接[   ] ,来返回拼接的String

public static String toString(int[] 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(a[i]);
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }
10.stream :返回对应类型流
  • stream​(double[] array)
    返回以指定数组作为源的顺序DoubleStream
  • stream​(double[] array, int startInclusive, int endExclusive)
    返回指定数组的指定范围作为其源的顺序DoubleStream 。
  • 其他类型类推

总结

  这些是我对常用的方法做了简单的收集整理,不得不说Arrays的底层实现真的很nb,值得反复看很多遍,这种编程思想值得学习借鉴!

未经允许不得转载!转载请注明来源。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Itfuture03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值