一、概述

1、介绍

  Arrays 类是 JDK1.2 提供的一个工具类,提供处理数组的各种方法,基本上都是静态方法,能直接通过类名Arrays调用。

二、类源码

1、asList()方法

  将一个泛型数组转化为List集合返回。但是,这个List集合既不是ArrayList实例,也不是Vector实例。它是一个固定长度的 List 集合,是 Arrays 的一个内部类 java.util.Arrays.ArrayList。
  代码示例:使用

 1 public class Main {
2 public static void main(String[] args) throws Exception {
3 Integer[] d = {3, 1, 2};
4 final List<Integer> integers = Arrays.asList(d);
5 System.out.println(integers);
6 }
7 }
8
9 // 结果
10 [3, 1, 2]

  源码示例:

1 public static <T> List<T> asList(T... a) {
2 return new ArrayList<>(a);
3 }
4
5 private static class ArrayList<E> extends AbstractList<E>
6 implements RandomAccess, java.io.Serializable
7 {
8 // 源码省略,读者可自行用idea查看
9 }

  说明:
  ①、定长列表,只能对其进行查看或者修改,不能进行添加或者删除操作

 1 public class Main {
2 public static void main(String[] args) {
3 String[] str = {"a", "b", "c"};
4 List<String> list = Arrays.asList(str);
5 // 可以进行修改
6 list.set(1, "e");
7 System.out.println(list.toString()); // [a, e, c]
8
9 list.add("a"); //添加元素会报错 java.lang.UnsupportedOperationException
10 }
11 }

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

1 // 类 AbstractList
2 public boolean add(E e) {
3 add(size(), e);
4 return true;
5 }
6
7 public void add(int index, E element) {
8 throw new UnsupportedOperationException();
9 }

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

 1 public class Main {
2 public static void main(String[] args) {
3 String[] str = {"a", "b", "c"};
4 final List<String> list = Arrays.asList(str);
5 System.out.println(list.size()); // 3
6
7 int[] i = {1, 2, 3};
8 final List<int[]> ints = Arrays.asList(i);
9 System.out.println(ints.size()); // 1
10
11 Integer[] in = {1, 2, 3};
12 final List<Integer> integers = Arrays.asList(in);
13 System.out.println(integers.size()); // 3
14 }
15 }

  类类型才是泛型,基本数据类型不能作为泛型的参数。读者根据上面结果自行体会一下。

  ③、返回的是原数组的里的引用,不是独立出来的集合对象

 1 public class Main {
2 public static void main(String[] args) {
3 String[] str = {"a", "b", "c"};
4 List<String> listStr = Arrays.asList(str);
5 System.out.println(Arrays.toString(str)); // [a, b, c]
6
7 listStr.set(0, "d");
8
9 System.out.println(Arrays.toString(str)); // [d, b, c]
10 }
11 }

  这里,修改的是返回的集合的内容,但是原数组的内容也变化了,所以只是返回了原数组的一个视图。如果希望返回一个全新的集合,可以如下:

 1 public class Main {
2 public static void main(String[] args) {
3 String[] str = {"a", "b", "c"};
4
5 ArrayList<String> strings = new ArrayList<>(Arrays.asList(str));
6 strings.add("d");
7
8 System.out.println(Arrays.toString(str)); // [a, b, c]
9 System.out.println(strings); // [a, b, c, d]
10 }
11 }

2、sort()方法

  用于数组排序,有一系列重载方法。注意,如果是 Object 类型,需要实现Comparable接口或者传入一个比较器 Comparator ,使其具有可比性。可以参考这篇。Java比较器。
  源码示例:

1 public static void sort(int[] a) {
2 DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
3 }

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

3、binarySearch()方法

  用于数组查找,是基于二分查找算法实现,有一系列重载方法,适用于各种基本数据类型以及对象数组。
  值得注意的是:调用此方法,要求待查找的数组有序。存在,返回元素下标;不存在,返回一个负数(不是 -1)。
  源码示例:

 1 public static int binarySearch(int[] a, int key) {
2 return binarySearch0(a, 0, a.length, key);
3 }
4
5 // 典型的二分查找算法
6 private static int binarySearch0(int[] a, int fromIndex, int toIndex,
7 int key) {
8 int low = fromIndex;
9 int high = toIndex - 1;
10
11 while (low <= high) {
12 int mid = (low + high) >>> 1;
13 int midVal = a[mid];
14
15 if (midVal < key)
16 low = mid + 1;
17 else if (midVal > key)
18 high = mid - 1;
19 else
20 return mid; // key found
21 }
22
23 // 找不到,返回并不是 -1
24 return -(low + 1); // key not found.
25 }

4、copyOf()方法

  拷贝数组元素。底层采用 System.arraycopy() 实现,这是一个native方法。
  注意:这个方法在ArrayList源码扩容时,也是用的它。
  代码示例:

 1 public class Main {
2 public static void main(String[] args) {
3 int[] old = {1, 3, 2};
4
5 int[] ints = Arrays.copyOf(old, 5);
6 System.out.println(Arrays.toString(ints)); // [1, 3, 2, 0, 0]
7
8 int[] ints1 = Arrays.copyOf(old, 1);
9 System.out.println(Arrays.toString(ints1)); // [1]
10 }
11 }

  源码示例:

 1 // Arrays类
2 public static int[] copyOf(int[] original, int newLength) {
3 int[] copy = new int[newLength];
4 System.arraycopy(original, 0, copy, 0,
5 // 长度是旧数组长度 与 新长度 取小
6 Math.min(original.length, newLength));
7 return copy;
8 }
9
10 // System类
11 public static native void arraycopy(Object src, int srcPos,
12 Object dest, int destPos,
13 int length);

  src:源数组
  srcPos:源数组要复制的起始位置
  dest:目的数组
  destPos:目的数组放置的起始位置
  length:复制的长度
  注意:src 和 dest都必须是同类型或者可以进行转换类型的数组。

5、equals()/deepEquals()方法

  ①、equals
  用于比较两个数组中对应位置的每一个元素是否相等。
  源码示例:

 1 // 基本数据类型数组比较
2 public static boolean equals(int[] a, int[] a2) {
3 // 引用相等,则相同
4 if (a==a2)
5 return true;
6 if (a==null || a2==null)
7 return false;
8
9 int length = a.length;
10 // 长度不同,则不相同
11 if (a2.length != length)
12 return false;
13
14 // 循环依次比较数组中每个元素是否相等
15 for (int i=0; i<length; i++)
16 if (a[i] != a2[i])
17 return false;
18
19 return true;
20 }
21
22 // 引用类型数组比较
23 public static boolean equals(Object[] a, Object[] a2) {
24 if (a==a2)
25 return true;
26 if (a==null || a2==null)
27 return false;
28
29 int length = a.length;
30 if (a2.length != length)
31 return false;
32
33 for (int i=0; i<length; i++) {
34 Object o1 = a[i];
35 Object o2 = a2[i];
36
37 // 对象相同通过 equals 方法判断
38 if (!(o1==null ? o2==null : o1.equals(o2)))
39 return false;
40 }
41
42 return true;
43 }

  ②、deepEquals
  比较两个数组的元素是否相等,可以嵌套任意层次的数组。
  源码就是递归的使用 deepEquals 判断每一层的数组是否相同。
  代码示例:

1 public class Main {
2 public static void main(String[] args) {
3 String[][] name1 = {{"G", "a", "o"}, {"H", "u", "a", "n"}, {"j", "i", "e"}};
4 String[][] name2 = {{"G", "a", "o"}, {"H", "u", "a", "n"}, {"j", "i", "e"}};
5
6 System.out.println(Arrays.equals(name1, name2));// false
7 System.out.println(Arrays.deepEquals(name1, name2));// true
8 }
9 }

6、fill()方法

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

1 public class Main {
2 public static void main(String[] args) {
3 int[] arr = new int[4];
4 System.out.println(Arrays.toString(arr)); // [0, 0, 0, 0]
5
6 Arrays.fill(arr, 6);
7 System.out.println(Arrays.toString(arr)); // [6, 6, 6, 6]
8 }
9 }

  源码示例:

 1 // 不写注释也能看懂的代码
2 public static void fill(int[] a, int val) {
3 for (int i = 0, len = a.length; i < len; i++)
4 a[i] = val;
5 }
6
7 public static void fill(int[] a, int fromIndex, int toIndex, int val) {
8 rangeCheck(a.length, fromIndex, toIndex);
9 for (int i = fromIndex; i < toIndex; i++)
10 a[i] = val;
11 }

7、toString 和 deepToString方法

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

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

最新文章

  1. C#中使用Linq实现全外连接
  2. Android Service提高
  3. git笔记 常规使用
  4. Spring进阶之路(1)-Spring核心机制:依赖注入/控制反转
  5. 程序语言的奥妙:算法解读 &mdash;&mdash;读书笔记
  6. mkinitrd 与 mkinitramfs
  7. 如何在Win10中启用和关闭管理员账户?
  8. Servlet的一些API使用介绍
  9. wamp 已安装cakephp Fatal error: You must enable the intl extension to use CakePHP. in XXX
  10. css3实现checkbox变按钮
  11. AngularJS2基本构造
  12. 【Java疑难杂症】利用Java核心库实现简单的AOP
  13. jsp 九大内置对象和其作用详解
  14. sqlalchemy 使用
  15. Nginx优化文件编写
  16. centos6 安装 docker 问题
  17. oracle无法通过IP地址进行连接
  18. django项目环境设置
  19. Ubuntu下编译opencv 和Ubuntu使用ffmpeg实现音频、视频的抽取
  20. 69. Sqrt(x)(二分查找)

热门文章

  1. 安装RHEL7配置本地yum源 -- yum不能安装时,在本地安装,亲测成功
  2. git忽略文件夹提交以及gitignore修改后不生效的解决办法
  3. C#基础知识---Lambda表达式
  4. C# 通过反射获取特性的值
  5. spring boot 2.0.0 + shiro + redis实现前后端分离的项目
  6. C++类和对象笔记
  7. webpack编译后的代码如何在浏览器执行
  8. React 性能调优记录(下篇),如何写高性能的代码
  9. Python3-sqlalchemy-orm 联表查询-无外键关系
  10. Shell中常用的语句