1.  Arrays类介绍

Arrays类是Java API中提供的类,在java.util包中,此类包含用来操作数组的各种方法,比如排序和搜索,在这个类中如果指定数组引用为null,则此类方法都会抛出NullPointerException,此类还包含一个允许将数组作为列表来查看的静态工厂。

Arrays类包含sort,binarySearch,equals,fill,copyOf,asList,hashCode,deepHashCode,deepEquals,toString和deepToString public方法供其他类使用。其中从java.lang.Object继承的方法有clone,equals,finalize,getClass hashCode,notify,notifyAll,toString,wait。sort方法用来排序,binarySearch方法是二分查找,equals方法是用来比较,fill方法用来将某个特定的值填充到数组中,copyOf复制特定长度的数组,asList方法的作用是将数组作为列表来查看。

Arrays类包含两个私有类,分别是LegacyMergeSort类和ArrayList类,gacMergeSort是老版本的归并排序实现,而ArrayList是一个数组队列,用于实现asList方法。

Arrays的构造函数

  1. private Arrays() {}

可以看到Arrays的构造函数被被设置为private的,表明这个类禁止使用默认构造函数并且不能被实例化,但是可以通过提供静态方法来使用这个类,这种模式就是单例模式。

Arrays方法摘要

  1. public static void sort(Object[] a)
  2. public static void sort(Object[] a, int fromIndex, int toIndex)
  3. public static <T> void sort(T[] a, Comparator<? super T> c)
  4. public static <T> void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c)
  5.  
  6. public static int binarySearch(Object[] a, Object key)
  7. public static int binarySearch(Object[] a, int fromIndex, int toIndex, Object key)
  8. public static <T> int binarySearch(T[] a, T key, Comparator<? super T> c)
  9. public static <T> int binarySearch(T[] a, int fromIndex, int toIndex, T key, Comparator<? super T> c)
  10.  
  11. public static boolean equals(Object[] a, Object[] a2)
  12.  
  13. public static void fill(Object[] a, Object val)
  14. public static void fill(Object[] a, int fromIndex, int toIndex, Object val)
  15. public static <T> T[] copyOf(T[] original, int newLength)
  16. public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType)
  17.  
  18. public static <T> T[] copyOfRange(T[] original, int from, int to)
  19. public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType)
  20.  
  21. public static <T> List<T> asList(T... a)
  22.  
  23. public static int hashCode(Object a[])
  24.  
  25. public static int deepHashCode(Object a[])
  26.  
  27. public static boolean deepEquals(Object[] a1, Object[] a2)
  28.  
  29. public static String toString(Object[] a)
  30.  
  31. public static String deepToString(Object[] a)

2.  Arrays类源码分析

依据JDK1.7.0_45的源码对Arrays类中的主要方法进行分析。

  1. public static void sort(Object[] a) {
  2. if (LegacyMergeSort.userRequested)
  3. legacyMergeSort(a);
  4. else
  5. ComparableTimSort.sort(a);
  6. }

此方法表示根据元素的自然顺序对指定对象数组按升序进行排序,当用户没有请求使用老版本的归并排序时,直接使用ComparableTimSort类的方法实现,关于ComparableTimSort类之后会单独进行分析。

  1. public static void sort(Object[] a, int fromIndex, int toIndex) {
  2. if (LegacyMergeSort.userRequested)
  3. legacyMergeSort(a, fromIndex, toIndex);
  4. else
  5. ComparableTimSort.sort(a, fromIndex, toIndex);
  6. }

此方法表示的是根据元素的自然顺序对指定对象数组的指定范围按升序进行排序,其他实现与上面的额排序方法相同。

  1. public static <T> void sort(T[] a, Comparator<? super T> c) {
  2. if (LegacyMergeSort.userRequested)
  3. legacyMergeSort(a, c);
  4. else
  5. TimSort.sort(a, c);
  6. }

此方法表示根据指定比较器产生的顺序对指定对象数组进行排序。具体的排序实现是调用了TimSort的sort方法实现。

  1. public static <T> void sort(T[] a, int fromIndex, int toIndex,
  2. Comparator<? super T> c) {
  3. if (LegacyMergeSort.userRequested)
  4. legacyMergeSort(a, fromIndex, toIndex, c);
  5. else
  6. TimSort.sort(a, fromIndex, toIndex, c);
  7. }

此方法表示根据指定比较器产生的顺序对指定对象数组的指定范围进行排序。同上具体的排序实现是调用了TimSort的sort方法实现。TimSort类在之后会单独分析。

  1. public static int binarySearch(Object[] a, Object key) {
  2. return binarySearch0(a, 0, a.length, key);
  3. }
  4.  
  5. // Like public version, but without range checks.
  6. private static int binarySearch0(Object[] a, int fromIndex, int toIndex,
  7. Object key) {
  8. int low = fromIndex;
  9. int high = toIndex - 1;
  10.  
  11. while (low <= high) {
  12. int mid = (low + high) >>> 1;
  13. Comparable midVal = (Comparable)a[mid];
  14. int cmp = midVal.compareTo(key);
  15.  
  16. if (cmp < 0)
  17. low = mid + 1;
  18. else if (cmp > 0)
  19. high = mid - 1;
  20. else
  21. return mid; // key found
  22. }
  23. return -(low + 1); // key not found.
  24. }

此方法表示使用二分搜索法来搜索指定数组,以获得指定对象,二分查找的具体实现没有进行范围检查。

  1. public static int binarySearch(Object[] a, int fromIndex, int toIndex,
  2. Object key) {
  3. rangeCheck(a.length, fromIndex, toIndex);
  4. return binarySearch0(a, fromIndex, toIndex, key);
  5. }

此方法表示使用二分搜索法来搜索指定数组的范围,以获得指定对象。

  1. public static <T> int binarySearch(T[] a, T key, Comparator<? super T> c) {
  2. return binarySearch0(a, 0, a.length, key, c);
  3. }
  4.  
  5. // Like public version, but without range checks.
  6. private static <T> int binarySearch0(T[] a, int fromIndex, int toIndex,
  7. T key, Comparator<? super T> c) {
  8. if (c == null) {
  9. return binarySearch0(a, fromIndex, toIndex, key);
  10. }
  11. int low = fromIndex;
  12. int high = toIndex - 1;
  13.  
  14. while (low <= high) {
  15. int mid = (low + high) >>> 1;
  16. T midVal = a[mid];
  17. int cmp = c.compare(midVal, key);
  18. if (cmp < 0)
  19. low = mid + 1;
  20. else if (cmp > 0)
  21. high = mid - 1;
  22. else
  23. return mid; // key found
  24. }
  25. return -(low + 1); // key not found.
  26. }

二分查找的的泛型实现,使用二分搜索法来搜索指定数组,以获得指定对象。

  1. public static <T> int binarySearch(T[] a, int fromIndex, int toIndex,
  2. T key, Comparator<? super T> c) {
  3. rangeCheck(a.length, fromIndex, toIndex);
  4. return binarySearch0(a, fromIndex, toIndex, key, c);
  5. }

二分查找的泛型实现,使用二分搜索法来搜索指定数组的范围,以获得指定对象。

  1. public static boolean equals(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<length; i++) {
  12. Object o1 = a[i];
  13. Object o2 = a2[i];
  14. if (!(o1==null ? o2==null : o1.equals(o2)))
  15. return false;
  16. }
  17.  
  18. return true;
  19. }

此方法为如果两个指定的 Objects 数组彼此相等,则返回 true。在具体的实现中如果两个Objects中有1个为null则返回false。

  1. public static void fill(Object[] a, Object val) {
  2. for (int i = 0, len = a.length; i < len; i++)
  3. a[i] = val;
  4. }

此方法表示将指定的 Object 引用分配给指定 Object 数组的每个元素。

  1. public static <T> T[] copyOf(T[] original, int newLength) {
  2. return (T[]) copyOf(original, newLength, original.getClass());
  3. }
  4.  
  5. public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
  6. T[] copy = ((Object)newType == (Object)Object[].class)
  7. ? (T[]) new Object[newLength]
  8. : (T[]) Array.newInstance(newType.getComponentType(), newLength);
  9. System.arraycopy(original, 0, copy, 0,
  10. Math.min(original.length, newLength));
  11. return copy;
  12. }

复制指定的数组,截取或用 null 填充(如有必要),以使副本具有指定的长度。这里注意对泛型的使用。,最终调用System.arraycopy函数进行复制操作。

  1. public static <T> T[] copyOfRange(T[] original, int from, int to) {
  2. return copyOfRange(original, from, to, (Class<T[]>) original.getClass());
  3. }
  4.  
  5. public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
  6. int newLength = to - from;
  7. if (newLength < 0)
  8. throw new IllegalArgumentException(from + " > " + to);
  9. T[] copy = ((Object)newType == (Object)Object[].class)
  10. ? (T[]) new Object[newLength]
  11. : (T[]) Array.newInstance(newType.getComponentType(), newLength);
  12. System.arraycopy(original, from, copy, 0,
  13. Math.min(original.length - from, newLength));
  14. return copy;
  15. }

将指定数组的指定范围复制到一个新数组。

  1. @SafeVarargs
  2. public static <T> List<T> asList(T... a) {
  3. return new ArrayList<>(a);
  4. }
  5.  
  6. /**
  7. * @serial include
  8. */
  9. private static class ArrayList<E> extends AbstractList<E>
  10. implements RandomAccess, java.io.Serializable
  11. {
  12. private static final long serialVersionUID = -2764017481108945198L;
  13. private final E[] a;
  14.  
  15. ArrayList(E[] array) {
  16. if (array==null)
  17. throw new NullPointerException();
  18. a = array;
  19. }
  20.  
  21. public int size() {
  22. return a.length;
  23. }
  24.  
  25. public Object[] toArray() {
  26. return a.clone();
  27. }
  28.  
  29. public <T> T[] toArray(T[] a) {
  30. int size = size();
  31. if (a.length < size)
  32. return Arrays.copyOf(this.a, size,
  33. (Class<? extends T[]>) a.getClass());
  34. System.arraycopy(this.a, 0, a, 0, size);
  35. if (a.length > size)
  36. a[size] = null;
  37. return a;
  38. }
  39.  
  40. public E get(int index) {
  41. return a[index];
  42. }
  43.  
  44. public E set(int index, E element) {
  45. E oldValue = a[index];
  46. a[index] = element;
  47. return oldValue;
  48. }
  49.  
  50. public int indexOf(Object o) {
  51. if (o==null) {
  52. for (int i=0; i<a.length; i++)
  53. if (a[i]==null)
  54. return i;
  55. } else {
  56. for (int i=0; i<a.length; i++)
  57. if (o.equals(a[i]))
  58. return i;
  59. }
  60. return -1;
  61. }
  62.  
  63. public boolean contains(Object o) {
  64. return indexOf(o) != -1;
  65. }
  66. }

返回一个受指定数组支持的固定大小的列表。@SafeVarargs注解抑制编译器警告的示例,只能用在参数长度可变的方法或构造方法上,且方法必须声明为static或final,否则会出现编译错误。一个方法使用@SafeVarargs注解的前提是,开发人员必须确保这个方法的实现中对泛型类型参数的处理不会引发类型安全问题。

  1. public static int hashCode(Object a[]) {
  2. if (a == null)
  3. return 0;
  4.  
  5. int result = 1;
  6.  
  7. for (Object element : a)
  8. result = 31 * result + (element == null ? 0 : element.hashCode());
  9.  
  10. return result;
  11. }

基于指定数组的内容返回哈希码。这个方法继承自java.lang.Object。

  1. public static int deepHashCode(Object a[]) {
  2. if (a == null)
  3. return 0;
  4.  
  5. int result = 1;
  6.  
  7. for (Object element : a) {
  8. int elementHash = 0;
  9. if (element instanceof Object[])
  10. elementHash = deepHashCode((Object[]) element);
  11. else if (element instanceof byte[])
  12. elementHash = hashCode((byte[]) element);
  13. else if (element instanceof short[])
  14. elementHash = hashCode((short[]) element);
  15. else if (element instanceof int[])
  16. elementHash = hashCode((int[]) element);
  17. else if (element instanceof long[])
  18. elementHash = hashCode((long[]) element);
  19. else if (element instanceof char[])
  20. elementHash = hashCode((char[]) element);
  21. else if (element instanceof float[])
  22. elementHash = hashCode((float[]) element);
  23. else if (element instanceof double[])
  24. elementHash = hashCode((double[]) element);
  25. else if (element instanceof boolean[])
  26. elementHash = hashCode((boolean[]) element);
  27. else if (element != null)
  28. elementHash = element.hashCode();
  29.  
  30. result = 31 * result + elementHash;
  31. }
  32.  
  33. return result;
  34. }

基于指定数组的“深层内容”返回哈希码。

  1. public static boolean deepEquals(Object[] a1, Object[] a2) {
  2. if (a1 == a2)
  3. return true;
  4. if (a1 == null || a2==null)
  5. return false;
  6. int length = a1.length;
  7. if (a2.length != length)
  8. return false;
  9.  
  10. for (int i = 0; i < length; i++) {
  11. Object e1 = a1[i];
  12. Object e2 = a2[i];
  13.  
  14. if (e1 == e2)
  15. continue;
  16. if (e1 == null)
  17. return false;
  18.  
  19. // Figure out whether the two elements are equal
  20. boolean eq = deepEquals0(e1, e2);
  21.  
  22. if (!eq)
  23. return false;
  24. }
  25. return true;
  26. }

如果两个指定数组彼此是深层相等 的,则返回 true

  1. public static String toString(Object[] a) {
  2. if (a == null)
  3. return "null";
  4.  
  5. int iMax = a.length - 1;
  6. if (iMax == -1)
  7. return "[]";
  8.  
  9. StringBuilder b = new StringBuilder();
  10. b.append('[');
  11. for (int i = 0; ; i++) {
  12. b.append(String.valueOf(a[i]));
  13. if (i == iMax)
  14. return b.append(']').toString();
  15. b.append(", ");
  16. }
  17. }

返回指定数组内容的字符串表示形式。

  1. public static String deepToString(Object[] a) {
  2. if (a == null)
  3. return "null";
  4.  
  5. int bufLen = 20 * a.length;
  6. if (a.length != 0 && bufLen <= 0)
  7. bufLen = Integer.MAX_VALUE;
  8. StringBuilder buf = new StringBuilder(bufLen);
  9. deepToString(a, buf, new HashSet<Object[]>());
  10. return buf.toString();
  11. }

返回指定数组“深层内容”的字符串表示形式。

3.  Arrays类的使用

一般主要使用Arrays类进行排序和查找,下面是简单的使用例子

  1. import java.util.Arrays;
  2. import java.util.Random;
  3.  
  4. class RandomString {
  5. private RandomString() {}
  6. public static String getString(int length) {
  7. String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  8. Random random = new Random();
  9. StringBuffer sb = new StringBuffer();
  10. for (int i = 0; i < length; i++) {
  11. int index = random.nextInt(base.length());
  12. sb.append(base.charAt(index));
  13. }
  14. return sb.toString();
  15. }
  16. }
  17.  
  18. public class ArraysTest {
  19. public static void main(String[] args) {
  20. int[] intArray = new int[10000000];
  21. String[] stringArray = new String[10000000];
  22. Random random = new Random();
  23.  
  24. // sort test
  25. for (int i = 0; i < intArray.length; i++) {
  26. intArray[i] = random.nextInt(1000000);
  27. }
  28. for (int j = 0; j < stringArray.length; j++) {
  29. stringArray[j] = RandomString.getString(random.nextInt(20));
  30. }
  31. long startTime = System.currentTimeMillis();
  32. Arrays.sort(intArray);
  33. long endTime = System.currentTimeMillis();
  34. System.out.println("sort int numbers cost: " + (endTime - startTime) + "ms");
  35.  
  36. startTime = System.currentTimeMillis();
  37. Arrays.sort(stringArray);
  38. endTime = System.currentTimeMillis();
  39. System.out.println("sort string numbers cost: " + (endTime - startTime) + "ms");
  40. //System.out.println(Arrays.toString(stringArray));
  41.  
  42. // search test
  43. startTime = System.nanoTime();
  44. Arrays.binarySearch(intArray, 97);
  45. endTime = System.nanoTime();
  46. System.out.println("search the numbers cost: " + (endTime - startTime) + "ns");
  47.  
  48. startTime = System.nanoTime();
  49. Arrays.binarySearch(stringArray, "abcdef");
  50. endTime = System.nanoTime();
  51. System.out.println("search the numbers cost: " + (endTime - startTime) + "ns");
  52. }
  53. }

可以看到在使用Arrays类的sort和二分查找函数时,当给10000000个整数和10000000个字符串排序并且做查找时消耗时间如下

sort int numbers cost: 1123ms
sort string cost: 13713ms
search the numbers cost: 15789ns
search the string cost: 39474ns

Arrays类的分析及使用的更多相关文章

  1. 7.Java集合-Arrays类实现原理及源码分析

    Java集合---Arrays类源码解析  转自:http://www.cnblogs.com/ITtangtang/p/3948765.html 一.Arrays.sort()数组排序 Java A ...

  2. 《java入门第一季》之Arrays类前传(排序案例以二分查找注意的问题)

    根据排序算法,可以解决一些小案例.举例如下: /* * 把字符串中的字符进行排序. * 举例:"dacgebf" * 结果:"abcdefg" * * 分析: ...

  3. 13-02 Java 数组高级算法,Arrays类

    冒泡排序 冒泡排序原理 冒泡排序代码: package cn.itcast_01; /* * 数组排序之冒泡排序: * 相邻元素两两比较,大的往后放,第一次完毕,最大值出现在了最大索引处 */ pub ...

  4. 01 语言基础+高级:1-3 常用API第一部分_day08【String类、static、Arrays类、Math类】

    day08[String类.static.Arrays类.Math类] String类static关键字Arrays类Math类 教学目标能够使用String类的构造方法创建字符串对象能够明确Stri ...

  5. Java数组声明创建和使用以及多维数组、Arrays类、稀疏数组

    目录 数组概述 数组声明创建 内存分析 java内存分析 堆 栈 方法区 三种初始化 静态初始化 动态初始化 数组的默认初始化 数组的四个基本特点 数组边界 小结: 数组使用 数组基础使用 For E ...

  6. 6、Arrays类

    Arrays类 Arrays里面包含了一系列静态方法,用于管理或操作数组(比如排序和搜索) 常用方法 toString 返回数组的字符串形式 Arrays.toString(arr) Integer[ ...

  7. MapReduce剖析笔记之八: Map输出数据的处理类MapOutputBuffer分析

    在上一节我们分析了Child子进程启动,处理Map.Reduce任务的主要过程,但对于一些细节没有分析,这一节主要对MapOutputBuffer这个关键类进行分析. MapOutputBuffer顾 ...

  8. 使用 Arrays 类操作 Java 中的数组

    Arrays 类是 Java 中提供的一个工具类,在 java.util 包中.该类中包含了一些方法用来直接操作数组,比如可直接实现数组的排序.搜索等(关于类和方法的相关内容在后面的章节中会详细讲解滴 ...

  9. Java Arrays类进行数组排序

    排序算法,基本的高级语言都有一些提供.C语言有qsort()函数,C++有sort()函数,java语言有Arrays类(不是Array).用这些排序时,都可以写自己的排序规则. Java API对A ...

随机推荐

  1. 解决 mininet gave up after 3 retries 问题

    解决 mininet gave up after 3 retries 问题 在通过mn启动mininet的时候遇到了如下问题: *** Creating network *** Adding cont ...

  2. 模拟C#的事件添加和删除

    从<C# Via CLR>中的演化的一个小demo,探索事件的添加和删除原理,简单明了: using System; using System.Collections.Generic; u ...

  3. YOLO V3论文理解

    YOLO3主要的改进有:调整了网络结构:利用多尺度特征进行对象检测:对象分类用Logistic取代了softmax. 1.Darknet-53 network在论文中虽然有给网络的图,但我还是简单说一 ...

  4. WPF几种高级绑定

    (1)Binding  + RelativeSource + AncestorType 模式  , 根据关联源所指定的类型,可动态绑定指定类型的Path属性(Path可以省略)(PS:动态指父级在运行 ...

  5. spoj Fast Multiplication

    题意:乘法 要用nlogn的fft乘法. //#pragma comment(linker,"/STACK:1024000000,1024000000") #include< ...

  6. 卸载 PrestaShop 1.7

    PrestaShop 的卸载非常简单: 在你的 Web 服务器上删除所有 PrestaShop 的文件和目录.你可以使用 FTP 客户端,你也可以使用 SSH 工具. 使用数据库工具删除数据库中所有以 ...

  7. thinkphp if标签

    1.thinkphp框架中的if标签,用于html页面中.在html中编写php代码 1).从控制器中得到数据在循环中if else 判断:<volist name="system_r ...

  8. Eclipse 汉化方法

    1 打开 http://www.eclipse.org/babel/downloads.php 2  复制 http://download.eclipse.org/technology/babel/u ...

  9. OAF 清空指定控件或区域的值

    CO if (pageContext.getParameter("ClearBtn") != null) { clearRegion(pageContext, webBean, & ...

  10. es-hadoop saveToEsWithMeta

    @Test def testEsRDDWriteWithDynamicMapping() { val doc1 = Map("one" -> null, "two& ...