java.util 1.8_JDK1.8源码(四)——java.util.Arrays 类

java.util.Arrays 类是 JDK 提供的一个工具类,用来处理数组的各种方法,而且每个方法基本上都是静态方法,能直接通过类名Arrays调用。

1、asList

public static ListasList(T... a) {return new ArrayList<>(a);

}

作用是返回由指定数组支持的固定大小列表。

注意:这个方法返回的 ArrayList 不是我们常用的集合类 java.util.ArrayList。这里的 ArrayList 是 Arrays 的一个内部类 java.util.Arrays.ArrayList。这个内部类有如下属性和方法:

80ea184c594f8bbd80fef3ff27ba45b6.png

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 private static class ArrayList extends AbstractList

2 implementsRandomAccess, java.io.Serializable3 {4 private static final long serialVersionUID = -2764017481108945198L;5 private finalE[] a;6

7 ArrayList(E[] array) {8 if (array==null)9 throw newNullPointerException();10 a =array;11 }12

13 public intsize() {14 returna.length;15 }16

17 publicObject[] toArray() {18 returna.clone();19 }20

21 public T[] toArray(T[] a) {22 int size =size();23 if (a.length ) a.getClass());26 System.arraycopy(this.a, 0, a, 0, size);27 if (a.length >size)28 a[size] = null;29 returna;30 }31

32 public E get(intindex) {33 returna[index];34 }35

36 public E set(intindex, E element) {37 E oldValue =a[index];38 a[index] =element;39 returnoldValue;40 }41

42 public intindexOf(Object o) {43 if (o==null) {44 for (int i=0; i

55 public booleancontains(Object o) {56 return indexOf(o) != -1;57 }58 }

View Code

①、返回的 ArrayList 数组是一个定长列表,我们只能对其进行查看或者修改,但是不能进行添加或者删除操作

通过源码我们发现该类是没有add()或者remove() 这样的方法的,如果对其进行增加或者删除操作,都会调用其父类 AbstractList 对应的方法,而追溯父类的方法最终会抛出 UnsupportedOperationException 异常。如下:

1 String[] str = {"a","b","c"};2 List listStr =Arrays.asList(str);3 listStr.set(1, "e");//可以进行修改

4 System.out.println(listStr.toString());//[a, e, c]

5 listStr.add("a");//添加元素会报错 java.lang.UnsupportedOperationException

e30746124ed4d2341dc05e365f8475a4.png

②、引用类型的数组和基本类型的数组区别

1 String[] str = {"a","b","c"};2 List listStr =Arrays.asList(str);3 System.out.println(listStr.size());//3

4

5 int[] i = {1,2,3};6 List listI =Arrays.asList(i);7 System.out.println(listI.size());//1

上面的结果第一个listStr.size()==3,而第二个 listI.size()==1。这是为什么呢?

我们看源码,在 Arrays.asList 中,方法声明为   List asList(T... a)。该方法接收一个可变参数,并且这个可变参数类型是作为泛型的参数。我们知道基本数据类型是不能作为泛型的参数的,但是数组是引用类型,所以数组是可以泛型化的,于是 int[] 作为了整个参数类型,而不是 int 作为参数类型。

所以将上面的方法泛型化补全应该是:

1 String[] str = {"a","b","c"};2 List listStr =Arrays.asList(str);3 System.out.println(listStr.size());//3

4

5 int[] i = {1,2,3};6 List listI = Arrays.asList(i);//注意这里List参数为 int[] ,而不是 int

7 System.out.println(listI.size());//1

8

9 Integer[] in = {1,2,3};10 List listIn = Arrays.asList(in);//这里参数为int的包装类Integer,所以集合长度为3

11 System.out.println(listIn.size());//3

③、返回的列表ArrayList里面的元素都是引用,不是独立出来的对象

1 String[] str = {"a","b","c"};2 List listStr =Arrays.asList(str);3 //执行更新操作前

4 System.out.println(Arrays.toString(str));//[a, b, c]

5 listStr.set(0, "d");//将第一个元素a改为d6 //执行更新操作后

7 System.out.println(Arrays.toString(str));//[d, b, c]

这里的Arrays.toString()方法就是打印数组的内容,后面会介绍。我们看修改集合的内容,原数组的内容也变化了,所以这里传入的是引用类型。

④、已知数组数据,如何快速获取一个可进行增删改查的列表List?

1 String[] str = {"a","b","c"};2 List listStr = new ArrayList<>(Arrays.asList(str));3 listStr.add("d");4 System.out.println(listStr.size());//4

这里的ArrayList 集合类后面我们会详细讲解,大家目前只需要知道有这种用法即可。

⑤、Arrays.asList() 方法使用场景

Arrays工具类提供了一个方法asList, 使用该方法可以将一个变长参数或者数组转换成List 。但是,生成的List的长度是固定的;能够进行修改操作(比如,修改某个位置的元素);不能执行影响长度的操作(如add、remove等操作),否则会抛出UnsupportedOperationException异常。

所以Arrays.asList 比较适合那些已经有数组数据或者一些元素,而需要快速构建一个List,只用于读取操作,而不进行添加或删除操作的场景。

2、sort

该方法是用于数组排序,在 Arrays 类中有该方法的一系列重载方法,能对7种基本数据类型,包括 byte,char,double,float,int,long,short 等都能进行排序,还有 Object 类型(实现了Comparable接口),以及比较器 Comparator 。

59b1dd7bad5b61a59912939969ba7e48.png

①、基本类型的数组

这里我们以 int[ ] 为例看看:

1 int[] num = {1,3,8,5,2,4,6,7};2 Arrays.sort(num);3 System.out.println(Arrays.toString(num));//[1, 2, 3, 4, 5, 6, 7, 8]

通过调用 sort(int[] a) 方法,将原数组按照升序的顺序排列。下面我们通过源码看看是如何实现排序的:

public static void sort(int[] a) {

DualPivotQuicksort.sort(a,0, a.length - 1, null, 0, 0);

}

在 Arrays.sort 方法内部调用 DualPivotQuicksort.sort 方法,这个方法的源码很长,分别对于数组的长度进行了各种算法的划分,包括快速排序,插入排序,冒泡排序都有使用。详细源码可以参考这篇博客。

②、对象类型数组

该类型的数组进行排序可以实现 Comparable 接口,重写 compareTo 方法进行排序。

1 String[] str = {"a","f","c","d"};2 Arrays.sort(str);3 System.out.println(Arrays.toString(str));//[a, c, d, f]

String 类型实现了 Comparable 接口,内部的 compareTo 方法是按照字典码进行比较的。

③、没有实现Comparable接口的,可以通过Comparator实现排序

1 Person[] p = new Person[]{new Person("zhangsan",22),new Person("wangwu",11),new Person("lisi",33)};2 Arrays.sort(p,new Comparator() {3 @Override4 public intcompare(Person o1, Person o2) {5 if(o1 == null || o2 == null){6 return 0;7 }8 return o1.getPage()-o2.getPage();9 }10 });11 System.out.println(Arrays.toString(p));

3、binarySearch

用二分法查找数组中的某个元素。该方法和 sort 方法一样,适用于各种基本数据类型以及对象。

注意:二分法是对以及有序的数组进行查找(比如先用Arrays.sort()进行排序,然后调用此方法进行查找)。找到元素返回下标,没有则返回 -1

实例:

1 int[] num = {1,3,8,5,2,4,6,7};2 Arrays.sort(num);3 System.out.println(Arrays.toString(num));//[1, 2, 3, 4, 5, 6, 7, 8]

4 System.out.println(Arrays.binarySearch(num, 2));//返回元素的下标 1

具体源码实现:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public static int binarySearch(int[] a, intkey) {2 return binarySearch0(a, 0, a.length, key);3 }4 private static int binarySearch0(int[] a, int fromIndex, int toIndex,intkey) {5 int low =fromIndex;6 int high = toIndex - 1;7

8 while (low <=high) {9 int mid = (low + high) >>> 1;//取中间值下标

10 int midVal = a[mid];//取中间值

11

12 if (midVal key)15 high = mid - 1;16 else

17 returnmid;18 }19 return -(low + 1);20 }

View Code

4、copyOf

拷贝数组元素。底层采用 System.arraycopy() 实现,这是一个native方法。

public static native void arraycopy(Object src, intsrcPos,

Object dest,intdestPos,int length);

src:源数组

srcPos:源数组要复制的起始位置

dest:目的数组

destPos:目的数组放置的起始位置

length:复制的长度

注意:src 和 dest都必须是同类型或者可以进行转换类型的数组。

int[] num1 = {1,2,3};int[] num2 = new int[3];

System.arraycopy(num1,0, num2, 0, num1.length);

System.out.println(Arrays.toString(num2));//[1, 2, 3]

/***@paramoriginal 源数组

*@paramnewLength //返回新数组的长度

*@return

*/

public static int[] copyOf(int[] original, intnewLength) {int[] copy = new int[newLength];

System.arraycopy(original,0, copy, 0,

Math.min(original.length, newLength));returncopy;

}

5、equals 和 deepEquals

①、equals

equals 用来比较两个数组中对应位置的每个元素是否相等。

9e5fd44f42e16ea521fd7c5c10d578c9.png

八种基本数据类型以及对象都能进行比较。

我们先看看 int类型的数组比较源码实现:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public static boolean equals(int[] a, int[] a2) {2 if (a==a2)//数组引用相等,则里面的元素一定相等

3 return true;4 if (a==null || a2==null)//两个数组其中一个为null,都返回false

5 return false;6

7 int length =a.length;8 if (a2.length != length)//两个数组长度不等,返回false

9 return false;10

11 for (int i=0; i

12 if (a[i] !=a2[i])13 return false;14

15 return true;16 }

View Code

在看对象数组的比较:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public static booleanequals(Object[] a, Object[] a2) {2 if (a==a2)3 return true;4 if (a==null || a2==null)5 return false;6

7 int length =a.length;8 if (a2.length !=length)9 return false;10

11 for (int i=0; i

18 return true;19 }

View Code

基本上也是通过 equals 来判断。

②、deepEquals

也是用来比较两个数组的元素是否相等,不过 deepEquals 能够进行比较多维数组,而且是任意层次的嵌套数组。

String[][] name1 = {{ "G","a","o" },{ "H","u","a","n"},{ "j","i","e"}};

String[][] name2= {{ "G","a","o" },{ "H","u","a","n"},{ "j","i","e"}};

System.out.println(Arrays.equals(name1,name2));//false

System.out.println(Arrays.deepEquals(name1,name2));//true

6、fill

该系列方法用于给数组赋值,并能指定某个范围赋值。

//给a数组所有元素赋值 val

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

a[i]=val;

}//给从 fromIndex 开始的下标,toIndex-1结尾的下标都赋值 val,左闭右开

public static void fill(int[] a, int fromIndex, int toIndex, intval) {

rangeCheck(a.length, fromIndex, toIndex);//判断范围是否合理

for (int i = fromIndex; i < toIndex; i++)

a[i]=val;

}

7、toString 和 deepToString

toString 用来打印一维数组的元素,而 deepToString 用来打印多层次嵌套的数组元素。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public static String toString(int[] a) {2 if (a == null)3 return "null";4 int iMax = a.length - 1;5 if (iMax == -1)6 return "[]";7

8 StringBuilder b = newStringBuilder();9 b.append('[');10 for (int i = 0; ; i++) {11 b.append(a[i]);12 if (i ==iMax)13 return b.append(']').toString();14 b.append(", ");15 }16 }

View Code

参考文档:https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值