一、概述

1、介绍

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

二、类源码

1、asList()方法

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

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

  源码示例:

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

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

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

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

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

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

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

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

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

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

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

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

2、sort()方法

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

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

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

3、binarySearch()方法

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

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

4、copyOf()方法

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

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

  源码示例:

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

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

5、equals()/deepEquals()方法

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

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

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

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

6、fill()方法

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

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

  源码示例:

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

7、toString 和 deepToString方法

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

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

JDK1.8源码(四)——java.util.Arrays类的更多相关文章

  1. JDK1.8源码(四)——java.util.Arrays 类

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

  2. JDK1.8源码(五)——java.util.Vector类

    JDK1.8源码(五)--java.lang. https://www.cnblogs.com/IT-CPC/p/10897559.html

  3. JDK1.8源码(七)——java.util.HashMap 类

    本篇博客我们来介绍在 JDK1.8 中 HashMap 的源码实现,这也是最常用的一个集合.但是在介绍 HashMap 之前,我们先介绍什么是 Hash表. 1.哈希表 Hash表也称为散列表,也有直 ...

  4. JDK1.8源码(五)——java.util.ArrayList 类

    关于 JDK 的集合类的整体介绍可以看这张图,本篇博客我们不系统的介绍整个集合的构造,重点是介绍 ArrayList 类是如何实现的. 1.ArrayList 定义 ArrayList 是一个用数组实 ...

  5. JDK1.8源码(六)——java.util.LinkedList 类

    上一篇博客我们介绍了List集合的一种典型实现 ArrayList,我们知道 ArrayList 是由数组构成的,本篇博客我们介绍 List 集合的另一种典型实现 LinkedList,这是一个有链表 ...

  6. JDK1.8源码(九)——java.util.LinkedHashMap 类

    前面我们介绍了 Map 集合的一种典型实现 HashMap ,关于 HashMap 的特性,我们再来复习一遍: ①.基于JDK1.8的HashMap是由数组+链表+红黑树组成,相对于早期版本的 JDK ...

  7. JDK1.8源码(十一)——java.util.TreeMap类

    在前面几篇博客分别介绍了这样几种集合,基于数组实现的ArrayList 类,基于链表实现的LinkedList 类,基于散列表实现的HashMap 类,本篇博客我们来介绍另一种数据类型,基于树实现的T ...

  8. JDK1.8源码(八)——java.util.HashSet 类

    在上一篇博客,我们介绍了 Map 集合的一种典型实现 HashMap ,在 JDK1.8 中,HashMap 是由 数组+链表+红黑树构成,相对于早期版本的 JDK HashMap 实现,新增了红黑树 ...

  9. JDK1.8源码(十)——java.util.LinkedHashSet类

    同 HashSet 与 HashMap 的关系一样,本篇博客所介绍的 LinkedHashSet 和 LinkedHashMap 也是一致的.在 JDK 集合框架中,类似 Set 集合通常都是由对应的 ...

随机推荐

  1. CleanArchitecture Application代码生成插件-让程序员告别CURD Ctrl+C Ctrl+V

    这是一个根据Domain项目中定义的实体对象(Entity)生成符合Clean Architecture原则的Application项目所需要的功能代码,包括常用的Commands,Queries,V ...

  2. stm32 connot enter debug mode

    dap 可以发现设备,stlink jlink 均无法发现设备,但是都不能下载.connot enter debug mode ,发现是vdda 未连接

  3. C# 正则表达式的重点知识 1

  4. C#基础知识---扩展方法

    一.简介 扩展方法为现有的类型(.Net类型或者自定义类型)扩展应该附加到该类型中的方法. 二.基本原则 定义一个非嵌套.非泛型的静态类 扩展方法是静态的 扩展方法至少要有一个参数,该参数类型是要扩展 ...

  5. SpringBoot快速搭建流程

    创建一个新项目 使用maven创建一个新项目 给定项目名称.finsh完成创建 跑起来SpringBoot 引入依赖parent > SpringBoot父级依赖,spring-boot-sta ...

  6. 字符串拷贝函数递归与非递归的C语言实现

    初学递归的时候,觉得很抽象,不好分析,确实如此,尤其是有些时候控制语句不对,导致程序进去无限次的调用,更严重的是栈溢出.既要正确的控制结束语句,又要有正确的进入下次递归的语句,还要有些操作语句.... ...

  7. 使用javascript纯前端导出excel

    前言(感谢技术的分享者) 参考博客地址 github地址 由SheetJS出品的js-xlsx是一款非常方便的只需要纯JS即可读取和导出excel的工具库,功能强大,支持格式众多,支持xls.xlsx ...

  8. transient用法

    1 import java.io.FileInputStream; 2 import java.io.FileNotFoundException; 3 import java.io.FileOutpu ...

  9. Python的GPU编程实例——近邻表计算

    技术背景 GPU加速是现代工业各种场景中非常常用的一种技术,这得益于GPU计算的高度并行化.在Python中存在有多种GPU并行优化的解决方案,包括之前的博客中提到的cupy.pycuda和numba ...

  10. Bing每日壁纸的RESTful接口实现

    0x00 存在意义 权且当作Docker打包的练习. 显然可以通过构造请求获得每天的壁纸,但是如果想要优雅地在其它地方使用这一网络资源,封装一个RESTful API将会保证整洁美观,在编写CSS等场 ...