一、概述

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. 浅谈 SQL 注入(注入篇)

    一.SQL注入简介 1.1 什么是SQL注入 在用户可控制的参数上过滤不严或没有任何限制,使得用户将传入的参数(如URL,表单,http header)与SQL语句合并构成一条 SQL语句传递给web ...

  2. 阿里云视频点播获取视频点播的video信息

    背景 因为在项目中需要使用阿里云的视频点播服务,需要获取视频点播的时长信息. 工具类 生成签名串Signature SignatureUtils.java package com.meeno.wzq. ...

  3. java批量下载文件为zip包

    批量下载文件为zip包的工具类 package com.meeno.trainsys.util; import javax.servlet.http.HttpServletRequest; impor ...

  4. SpringBoot返回枚举对象中的指定属性

    枚举 package com.meeno.boot.oa.employee.enums; import com.alibaba.fastjson.annotation.JSONType; import ...

  5. springboot 2.0 整合 RestTemplate

    首先导入springboot 的 web 包 <dependency> <groupId>org.springframework.boot</groupId> &l ...

  6. SpringMVC的拦截器和过滤器的区别

    一 简介 (1)过滤器: 依赖于servlet容器.在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次.使用过滤器的目的是用来做一些过滤操作,获取我们 ...

  7. C#多线程---线程池的工作者线程

    一.线程池简介 创建和销毁线程是一个要耗费大量时间的过程,太多的线程也会浪费内存资源,所以通过Thread类来创建过多的线程反而有损于性能,为了改善这样的问题 ,.net中就引入了线程池. 线程池形象 ...

  8. 十:JavaWeb中的监听器(一)

    2.1.基本概念 JavaWeb中的监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序中的ServletContext, HttpSession和 ServletRequest等域 ...

  9. vue2.0中模拟数据的配置

    在开发过程中,有时候接口跟不上我们的进度,我们要测试,就需要自测. 现在vue已经升级到2.0版本了,早期在vue构建工程文件在build里面有dev-server.js,但是后来构建去除了该文件集成 ...

  10. Spring 钩子之BeanFactoryPostProcessor和BeanPostProcessor的源码学习,FactoryBean

    BeanFactoryPostProcessor 是用于增强BeanFactory的(例如可以增强beanDefination), BeanPostProcessor是用于增强bean的,而Facto ...