1. 程式人生 > >java.util.Arrays類詳解(原始碼總結)

java.util.Arrays類詳解(原始碼總結)

概述

Arrays類位於java.util包下,是一個對陣列操作的工具類。今天詳細的看了看Arrays類的4千多行原始碼,現將Arrays類中的方法做一個總結(JDK版本:1.6.0_34)。Arrays類中的方法可以分為八類:

  • sort(對陣列排序)
  • binarySearch(二分法查詢陣列中的元素)
  • equals(比較兩個陣列是否相等)
  • fill(對陣列中的指定位置填充相同的內容)
  • copyOf(陣列拷貝)
  • asList(將陣列轉換為一個固定的List物件)
  • hashCode(計算陣列的雜湊值)
  • toString(以特定格式輸出陣列)

舉例說明

說明:以下的程式碼均為摘抄的java.util.Arrays類中的原始碼,註釋為本人所加。

sort

//對陣列a進行排序
public static void sort(long[] a) {
        sort1(a, 0, a.length);
    }
//對陣列a中的從fromIndex(包含)至toIndex(不包含)的值進行排序
public static void sort(long[] a, int fromIndex, int toIndex) {
        rangeCheck(a.length, fromIndex, toIndex);
        sort1(a, fromIndex, toIndex-fromIndex);
    }
/**
對基本型別陣列的排序有以上兩種方法,這裡只摘出了long型別的。sort1方法篇幅原因沒有摘出來,在sort1方法中使用的是經過調優的快速排序演算法(tuned quicksort)。
**/
.......... .......... .......... //對物件型別進行排序 public static void sort(Object[] a) { Object[] aux = (Object[])a.clone(); mergeSort(aux, a, 0, a.length, 0); } //對物件a中的從fromIndex(包含)至toIndex(不包含)的值進行排序 public static void sort(Object[] a, int fromIndex, int toIndex) { rangeCheck(a.length, fromIndex, toIndex); Object[] aux = copyOfRange(a, fromIndex, toIndex); mergeSort(aux, a, fromIndex, toIndex, -fromIndex); } /** 對物件型別陣列的排序有以上兩種方法,在mergeSort方法中使用的是經過修改的歸併排序演算法(modified mergesort)。 **/

binarySearch

 public static int binarySearch(long[] a, long key) {
    return binarySearch0(a, 0, a.length, key);
    }
 public static int binarySearch(long[] a, int fromIndex, int toIndex,
                   long key) {
    rangeCheck(a.length, fromIndex, toIndex);
    return binarySearch0(a, fromIndex, toIndex, key);
    }
/**
對陣列中元素的查詢有以上兩種方法,在binarySearch0方法中使用的是二分查詢法。並且對基本型別和物件型別的陣列查詢是同樣的操作。
**/

equals

//比較基本型別陣列是否相等
 public static boolean equals(long[] a, long[] a2) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;
/**
        對於double型別,使用的是: 
        if (Double.doubleToLongBits(a[i])!=Double.doubleToLongBits(a2[i]))
        return false;
        對於float型別,使用的是:
         if (Float.floatToIntBits(a[i])!=Float.floatToIntBits(a2[i]))
                return false;
這樣做是為了精確比較。
        **/
        return true;
    }
.....
.....
.....
//比較Object型別陣列是否相等
public static boolean equals(Object[] a, Object[] a2) {
        if (a==a2)
            return true;
        if (a==null || a2==null)
            return false;

        int length = a.length;
        if (a2.length != length)
            return false;

        for (int i=0; i<length; i++) {
            Object o1 = a[i];
            Object o2 = a2[i];
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }

        return true;
    }
.....
.....
.....
//深度比較兩個陣列是否相等
 public static boolean deepEquals(Object[] a1, Object[] a2) {
        if (a1 == a2)
            return true;
        if (a1 == null || a2==null)
            return false;
        int length = a1.length;
        if (a2.length != length)
            return false;

        for (int i = 0; i < length; i++) {
            Object e1 = a1[i];
            Object e2 = a2[i];

            if (e1 == e2)
                continue;
            if (e1 == null)
                return false;

            // Figure out whether the two elements are equal
            boolean eq;
            if (e1 instanceof Object[] && e2 instanceof Object[])
                eq = deepEquals ((Object[]) e1, (Object[]) e2);
            else if (e1 instanceof byte[] && e2 instanceof byte[])
                eq = equals((byte[]) e1, (byte[]) e2);
            else if (e1 instanceof short[] && e2 instanceof short[])
                eq = equals((short[]) e1, (short[]) e2);
            else if (e1 instanceof int[] && e2 instanceof int[])
                eq = equals((int[]) e1, (int[]) e2);
            else if (e1 instanceof long[] && e2 instanceof long[])
                eq = equals((long[]) e1, (long[]) e2);
            else if (e1 instanceof char[] && e2 instanceof char[])
                eq = equals((char[]) e1, (char[]) e2);
            else if (e1 instanceof float[] && e2 instanceof float[])
                eq = equals((float[]) e1, (float[]) e2);
            else if (e1 instanceof double[] && e2 instanceof double[])
                eq = equals((double[]) e1, (double[]) e2);
            else if (e1 instanceof boolean[] && e2 instanceof boolean[])
                eq = equals((boolean[]) e1, (boolean[]) e2);
            else
                eq = e1.equals(e2);

            if (!eq)
                return false;
        }
        return true;
    }

fill

//使用val對a陣列進行資料填充
  public static void fill(long[] a, long val) {
        fill(a, 0, a.length, val);
    }
//使用val對a陣列從fromIndex(包含)至toIndex(不包含)位置進行資料填充
 public static void fill(long[] a, int fromIndex, int toIndex, long val) {
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i=fromIndex; i<toIndex; i++)
            a[i] = val;
    }

copyOf

//拷貝從0開始的newLength個
public static byte[] copyOf(byte[] original, int newLength) {
        byte[] copy = new byte[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
.....
.....
.....
//拷貝從from(包含)位置到to(不包含)的元素
public static byte[] copyOfRange(byte[] original, int from, int to) {
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        byte[] copy = new byte[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }
/**
拷貝方法有以上兩種,對於基本型別和物件操作是一樣的。而System.arraycopy()方法為淺拷貝,故如果是物件陣列的拷貝,只是拷貝了物件的引用,沒有重新new每一個物件。
**/

asList

沒有深究。。。。。。

hashCode

//對基本資料型別的hashcode的計算
    public static int hashCode(long a[]) {
        if (a == null)
            return 0;

        int result = 1;
        for (long element : a) {
        //對於不同的基本資料型別,計算hashcode的具體操作是不一樣的
            int elementHash = (int)(element ^ (element >>> 32));
            result = 31 * result + elementHash;
        }

        return result;
    }
....
....
....
//對於Object型別陣列的hashcode的計算
public static int hashCode(Object a[]) {
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a)
            result = 31 * result + (element == null ? 0 : element.hashCode());

        return result;
    }
....
....
....
//對於陣列的hashcode值的深度計算
public static int deepHashCode(Object a[]) {
        if (a == null)
            return 0;

        int result = 1;

        for (Object element : a) {
            int elementHash = 0;
            if (element instanceof Object[])
                elementHash = deepHashCode((Object[]) element);
            else if (element instanceof byte[])
                elementHash = hashCode((byte[]) element);
            else if (element instanceof short[])
                elementHash = hashCode((short[]) element);
            else if (element instanceof int[])
                elementHash = hashCode((int[]) element);
            else if (element instanceof long[])
                elementHash = hashCode((long[]) element);
            else if (element instanceof char[])
                elementHash = hashCode((char[]) element);
            else if (element instanceof float[])
                elementHash = hashCode((float[]) element);
            else if (element instanceof double[])
                elementHash = hashCode((double[]) element);
            else if (element instanceof boolean[])
                elementHash = hashCode((boolean[]) element);
            else if (element != null)
                elementHash = element.hashCode();

            result = 31 * result + elementHash;
        }

        return result;
    }

toString

//基本資料型別轉字串
    public static String toString(long[] a) {
        if (a == null)
            return "null";
    int iMax = a.length - 1;
    if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(a[i]);
        if (i == iMax)
        return b.append(']').toString();
            b.append(", ");
        }
    }
.....
.....
.....
//Object型別使用valueOf方法轉字串
public static String toString(Object[] a) {
        if (a == null)
            return "null";
    int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
    b.append('[');
        for (int i = 0; ; i++) {
            b.append(String.valueOf(a[i]));
            if (i == iMax)
        return b.append(']').toString();
        b.append(", ");
        }
    }
.....
.....
.....
//深度轉換字串
public static String deepToString(Object[] a) {
        if (a == null)
            return "null";

        int bufLen = 20 * a.length;
        if (a.length != 0 && bufLen <= 0)
            bufLen = Integer.MAX_VALUE;
        StringBuilder buf = new StringBuilder(bufLen);
        deepToString(a, buf, new HashSet());
        return buf.toString();
    }

private static void deepToString(Object[] a, StringBuilder buf,
                                     Set<Object[]> dejaVu) {
        if (a == null) {
            buf.append("null");
            return;
        }
        dejaVu.add(a);
        buf.append('[');
        for (int i = 0; i < a.length; i++) {
            if (i != 0)
                buf.append(", ");

            Object element = a[i];
            if (element == null) {
                buf.append("null");
            } else {
                Class eClass = element.getClass();

                if (eClass.isArray()) {
                    if (eClass == byte[].class)
                        buf.append(toString((byte[]) element));
                    else if (eClass == short[].class)
                        buf.append(toString((short[]) element));
                    else if (eClass == int[].class)
                        buf.append(toString((int[]) element));
                    else if (eClass == long[].class)
                        buf.append(toString((long[]) element));
                    else if (eClass == char[].class)
                        buf.append(toString((char[]) element));
                    else if (eClass == float[].class)
                        buf.append(toString((float[]) element));
                    else if (eClass == double[].class)
                        buf.append(toString((double[]) element));
                    else if (eClass == boolean[].class)
                        buf.append(toString((boolean[]) element));
                    else { // element is an array of object references
                        if (dejaVu.contains(element))
                            buf.append("[...]");
                        else
                            deepToString((Object[])element, buf, dejaVu);
                    }
                } else {  // element is non-null and not an array
                    buf.append(element.toString());
                }
            }
        }
        buf.append(']');
        dejaVu.remove(a);
    }

相關推薦

java.util.Arrays原始碼總結

概述 Arrays類位於java.util包下,是一個對陣列操作的工具類。今天詳細的看了看Arrays類的4千多行原始碼,現將Arrays類中的方法做一個總結(JDK版本:1.6.0_34)。Arrays類中的方法可以分為八類: sort(對陣列排序) b

Java Scanner 附例子學習

在筆試程式設計過程中,關於資料的讀取如果迷迷糊糊,那後來的程式設計即使想法很對,實現很好,也是徒勞,於是在這裡認真總結了Java  Scanner 類的使用 通過 Scanner 類來獲取使用者的輸入,下面是建立 Scanner 物件的基本語法: Scanner s =

Java入門提高篇】Day34 Java容器十五WeakHashMap

public class WeakHashMapTest { public static void main(String[] args){ testWeakHashMap(); } private static void testWeakHashMap

java常用集合有例子,集合糊塗的來看!

TreeSet:TreeSet是依靠TreeMap來實現的.TreeSet是一個有序集合,TreeSet中元素將按照升序排列,預設是按照自然排序進行排列,意味著TreeSet中元素要實現Comparable介面.我們可以在構造TreeSet物件時,傳遞實現了Comparator介面的比較器物件.java.ut

Java 原子操作AtomicInteger、AtomicIntegerArray等

當程式更新一個變數時,如果多執行緒同時更新這個變數,可能得到期望之外的值,比如變數i=1,A執行緒更新i+1,B執行緒也更新i+1,經過兩個執行緒操作之後可能i不等於3,而是等於2。因為A和B執行緒在更新變數i的時候拿到的i都是1,這就是執行緒不安全的更新操作,通常我們會使

Type的子介面原始碼解析

以下是原始碼中對Type的註釋:Type是Java中所有型別的常見的超介面,在程式語言中這些包括原始型別,引數化的型別,陣列型別,型別變數和原始型別。 Class在一定程度上挽救了擦除的型別資訊,我們就可以通過這幾個介面來獲取被擦除的型別引數資訊,這幾個介面無非就是對型別引數的一個

JDK動態代理原始碼剖析

一、什麼是代理? 代理是一種常用的設計模式,其目的就是為其他物件提供一個代理以控制對某個物件的訪問。代理類負責為委託類預處理訊息,過濾訊息並轉發訊息,以及進行訊息被委託類執行後的後續處理。代理模式UML圖:簡單結構示意圖:為了保持行為的一致性,代理類和委託類通常

openCV中的findHomography函式分析以及RANSAC演算法的原始碼分析

本文將openCV中的RANSAC程式碼全部挑選出來,進行分析和講解,以便大家更好的理解RANSAC演算法。程式碼我都試過,可以直接執行。 在計算機視覺和影象處理等很多領域,都需要用到RANSAC演算法。openCV中也有封裝好的RANSAC演算法,以便於人們使用。關於RA

cas客戶端流程原始碼解析--單點登入

博主之前一直使用了cas客戶端進行使用者的單點登入操作,決定進行原始碼分析來看cas的整個流程,以便以後出現了問題還不知道是什麼原因導致的 cas主要的形式就是通過過濾器的形式來實現的,來,貼上示例配置: 1 <listener> 2 <listener-cl

hadoop3叢集搭建自身總結

hadoop3 確定叢集所需要的機器 ,我由於機器限制 只有三臺機器,一般的資料節點至少要有三個副本 由於機器限制我這裡就用了兩個副本了(我這裡hadoop01是主節點) hadoop01 hadoop02 hadoop03 三臺伺服器 伺服器環境搭建 hado

Java併發十二:CAS Unsafe Atomic 說一說Java的Unsafe 說一說Java的Unsafe Java中Unsafe Unsafe與CAS

一、Unsafe Java無法直接訪問底層作業系統,而是通過本地(native)方法來訪問。不過儘管如此,JVM還是開了一個後門,JDK中有一個類Unsafe,它提供了硬體級別的原子操作。 這個類儘管裡面的方法都是public的,但是並沒有辦法使用它們,JDK API文件也沒有提供任何關於這個類的方法的解

Java 的 IO 四大基

1、概述      Java 的IO通過java.io 包下的類和介面來支援,java.io包下主要包括輸入、輸出兩種流。每種輸入輸出流又可分為位元組流和字元流兩大類。      位元組流以位元組為單位處理輸入、輸出操作;      字元流以字元來處理輸入

Java String

String類是一個字串型別的類,使用“XXXX”定義的內容都是字串,雖然這個類在使用上有一些特殊,但是String本身是一個類。 一、String的例項化兩種方式 1、直接賦值例項化: String StringName= "xxx"; 以上是Stri

java Io 流

修改 文件目錄 != exe [] 深入 clas one fileinput 關於java 流類的復習;習慣性的復習按照圖結構一層層往下深入去了解去復習,最後通過代碼來實現感覺印象會更深刻一些; 關於 I/O流:IO可以理解為JAVA用來傳遞數據的管道

Java 多線程------線程的同步

alt 來看 監聽 介紹 創建進程 java 多線程 system ima 關鍵字 Java 多線程詳解(一)------概念的引入:http://www.cnblogs.com/ysocean/p/6882988.html Java 多線程詳解(二)------如何創建進

10.5-全棧Java筆記:常見流

java上節我們講到「Java中常用流:緩沖流」,本節我們學習數據流和對象流~ 數據流數據流將“基本數據類型變量”作為數據源,從而允許程序以與機器無關方式從底層輸入輸出流中操作java基本數據類型。 DataInputStream和DataOutputStream提供了可以存取與機器無關的所有Java基礎類

Java的反射機制

pbc spa 詳解 uno face target lan tor cin 8n72q傅釁8戰sig叢http://www.docin.com/app/user/userinfo?userid=179185461 8u炊3F7LB椒1http://huiyi.docin.

PHP與Java集成開發

new 編程語言 到你 其中 web-inf request 測試 add 輸入 很久以前,有人從www上看到看到天空上一個很亮的亮點,它就是Java語言,與此同時,在另一個地方一位夢想家也看到了一個亮點,它就是PHP。 時間一天天過去,這兩個亮點也變得越來越亮,很快,它

System.AppDomain

AppDomain是CLR(Common Language Runtime:公共語言執行庫),它可以載入Assembly、建立物件以及執行程式。 AppDomain是CLR實現程式碼隔離的基本機制。 每一個AppDomain可以單獨執行、停止;每個AppDomain都有自己預設的異常

Java併發工具

在JDK的併發包裡提供了幾個非常有用的併發工具類。CountDownLatch、CyclicBarrier和Semaphore工具類提供了一種併發流程控制的手段,Exchanger工具類則提供了線上程間交換資料的一種手段。本章會配合一些應用場景來介紹如何使用這些工具類。 等待多執行緒完成的Cou