首頁  >  文章  >  Java  >  Java 數組程式碼實例綜述

Java 數組程式碼實例綜述

黄舟
黄舟原創
2017-03-14 11:54:041494瀏覽


摘要

#  本文主要闡述了Java 中與陣列的知識,主要從陣列與容器、陣列的建立與初始化、陣列與泛型、陣列與可變參數清單、Arrays 工具類別的實用功能五個面向來對陣列進行詳細說明和總結。


一.要點概覽

  • 陣列與容器

  • 陣列的建立與初始化

  • 陣列與泛型

  • 」陣列與可變參數清單

  • Arrays 工具類的實用功能

  • 總結


#二.陣列與容器

  在Java 中,陣列與容器都可以持有物件,那麼,陣列與容器的差別是什麼呢?當我們需要持有物件時,我們在什麼情況下應優先選用數組,而又在什麼情況下優先選用容器呢?


  在Java 的初始版本中,尺寸固定的陣列絕對是必要的,不僅因為Java 設計者選擇在Java 中要包含基本類型和一些基於效能方面的考量,而且還因為初始版本對容器的支援非常少。因此,在Java 早期版本中,選擇包含陣列總是合理的,具體表現在以下三個方面:

  • #效率

      在Java 中,陣列是一種效率最高的儲存和隨機存取物件引用序列的方式。數組就是一個簡單的線性序列,這使得元素存取非常快速。 但是,為此速度所付出的代價是數組物件的大小被固定,並且在其生命週期中不可改變。 由於 ArrayList 可以實現空間的自動分配並且更為靈活,所以,我們通常應首選 ArrayList 而不是數組,但這種彈性需要開銷。因此,ArrayList 的效率比數組低的多。

  • 型別

      在 JDK 1.5 之前,Java 並未引進泛型。所以,泛型之前的容器類別在處理物件時,都將它們視為沒有任何具體類型,即將這些物件都當作 Object 來處理。數組之所以優於泛型之前的容器,就是因為你可以建立一個陣列去持有某種具體的類型。這意味著你可以透過編譯期的類型檢查來防止插入錯誤類型和抽取不當類型。 當然,無論在編譯時或執行時,Java都會阻止你向物件發送不恰當的訊息。所以,並不是說哪種方法更不安全,只是若編譯時就能夠指出錯誤,會顯得更優雅。

  • 儲存基本型別的能力

      陣列可以持有基本型,而泛型之前的容器則不能。

      在JDK 1.5 之後,Java 引進了泛型和自動包裝機制(泛型可以保證產生類型安全的容器,自動包裝機制使容器可以持有基本類型),這使得現在的容器在除了性能之外的各個方面都使得數組相形見絀。 另外,泛型對陣列是極大的威脅,而且通常狀況下,二者不能很好地結合(不能實例化具有參數化類型的陣列) 。

      因此,當我們使用最近的Java版本程式時,應優先選擇容器而非陣列。 只有在已證明效能成為問題並且切換到陣列對效能提高有所幫助時,我們才應該將程式重構為使用陣列。


三.陣列的建立與初始化

1、陣列基礎

  • 陣列標識符只是一個引用,指向在堆中創建的一個真實對象,這個對像用以保存指向其他對象的引用或基本類型的值;

  • 對象數組保存的是引用,基本類型數組直接保存基本類型的值;

  • “[ ]” 語法是存取陣列物件的唯一方式;


2、建立與初始化

  • 作為陣列初始化的一部分隱式創建

String[] strs = { ... };    
// 创建方式 1 --- 花括号内对象的个数就是数组大小System.out.println(strs.length);    
// 输出 0
String[] strs = new String[5];  
//创建方式 2String[] ss = new String[]{ ... };   
//创建方式 3

3、多維數組

  多維數組的本質:數組的元素仍是數組

// 创建方式 1int[][] a = { 
{ 1, 2, 3, }, 
{ 4, 5, 6, }, 
}; 

// 创建方式 2int[][][] a = new int[2][2][4];//粗糙数组:每个向量具有任意长度Random rand = new Random(47); 

// 3-D array with varied-length vectors: int[][][] a = new int[rand.nextInt(7)][][]; 

for(int i = 0; i < a.length; i++) { 
    a[i] = new int[rand.nextInt(5)][]; 
    for(int j = 0; j < a[i].length; j++) 
        a[i][j] = new int[rand.nextInt(5)]; 
}

四、陣列與泛型

  • 陣列與泛型不能很好的結合,也就是說,不能實例化具有參數化型別的陣列;

T[] first = new T[3];    
// ERROR  A<String>[] arrays = new A<String>[4];    
// ERROR: Cannot create a generic array of A<String>
  • #可以建立泛型陣列參考;

A<String>[] arrays;    
// OK
  • 陣列是協變的;

#
Object[] objs = new String[3];      
// OK

  總之,泛型容器總是比泛型陣列更好的選擇。


五、陣列與可變參數類型

1、可變參數類型概念

#  Java SE5 新增了可變參數類型( Variable Argument Type ),形式為“Type… args”,只可用作方法的參數可變參數清單適用於參數個數不確定但類型決定的情形 ( java 把可變參數當作陣列處理 )。 特別要注意的是,可變參數清單必須位於最後一項 (即最多只支援一個可變參數)。 當可變參數清單個數多餘一個時,必會有一個不是最後一項,所以只支援一個可變參數。因為可變參數清單的參數個數不確定,所以當其後邊還有相同型別參數時,Java 無法區分傳入的參數屬於前一個可變參數還是後邊的參數,所以只能讓可變參數位於最後一項。

// 代码示例public class TestVarArgus {  
    public static void dealArray(int... intArray){  
        for (int i : intArray)  
            System.out.print(i +" ");  

        System.out.println();  
    }  

    public static void main(String args[]){  
        dealArray();  
        dealArray(1);  
        dealArray(1, 2, 3);  
    }  
}/* Output:

        1   
        1 2 3   
 *///:~

可變參數清單具有以下特點:

  • #只能出現在方法參數清單的最後;

  • # 位於變數類型與變數名稱之間,前後有無空格都可以;

  • #呼叫可變參數所在的方法時,編譯器會為該可變參數隱式建立一個數組,這樣我們就可以在方法體中以數組的形式存取可變參數列表(編譯器把可變參數當作數組處理)


2、可變參數型別與陣列的兼容性

  • 編譯器認為數組類型和可變參數類型是相同的,即二者不能重載;

public class TestVarArgus {  
    public static void dealArray(int... intArray){  
        for (int i : intArray)  
            System.out.print(i +" ");  

        System.out.println();  
    }  

    //ERROR : Duplicate method dealArray(int[]) in type TestVarArgus 
    public static void dealArray(int[] intArray){    
        for (int i : intArray)  
            System.out.print(i +" ");  

        System.out.println();  
    }  

    public static void main(String args[]){  
        dealArray();   
        dealArray(1);  
        dealArray(1, 2, 3);  
    }  
}


  • #可變參數是相容於陣列類型參數的,但是陣列類型參數卻無法相容於可變參數;

// 代码示例 1 : 给参数为可变参数类型的方法传递数组public class TestVarArgus {  
    public static void dealArray(int... intArray){  
        for (int i : intArray)  
            System.out.print(i +" ");  

        System.out.println();  
    }  

    public static void main(String args[]){  
        int[] intArray = {1, 2, 3};  

        dealArray(intArray);  // OK
    }  
}
// 代码示例 2 : 给参数为数组类型的方法传递可变参数public class TestVarArgus {  
    public static void dealArray(int[] intArray){  
        for (int i : intArray)  
            System.out.print(i +" ");  

        System.out.println();  
    }  

    public static void main(String args[]){  
        dealArray(1, 2, 3);     // ERROR
    }  
}

  
    其實,對於範例程式碼2 而言,只是需要一個定義為deal​​Array(int, int, int)的方法或是一個定義為deal​​Array(int… )的方法。所以,自然就無法去匹配具有陣列類型的參數 dealArray( int[] ) 方法了。
  • 參數匹配原則:能匹配定長的方法,那麼

    優先

    # 匹配該方法;

public class TestVarArgus { //含有不定参数的那个重载方法是最后被选中的public static void dealArray(int... intArray){  
    System.out.println("Bad");  
}  

public static void dealArray(int count, int count2){  
    System.out.println("Bingo");  
}  

public static void main(String args[]){  
    dealArray(1, 2);  
}  
} /* Output:
        Bingo 
*///:~

#############就連我們耳熟能詳的main ###函數的參數# ##也能改寫成可變參數類型的形式:public static void main(String… args) .############        ############### ###六、Arrays 工具類別的實用功能######1、複製陣列###null
Function Introduction #Note
System.arraycopy( Object src, int srcPos, #Object dest, int destPos, int length) #從指定來源陣列中複製一個數組,複製從指定的位置開始,到目標數組的指定位置結束 若複製物件數組,那麼只是複製了物件的引用,而不是物件本身的拷貝(淺複製);該方法不會執行自動包裝和自動拆包,所以兩個數組必須具有相同的確切類型;須明確自行新建立一個數組對象,作為副本
copyOf(T[] original, int newLength) 複製指定的數組,
填入##################底層呼叫的還是System.arraycopy;傳回一個新的陣列對象,若新數組的長度超過原數組的長度,則保留數組預設值###################

 
注意:

 对于以上两个方法:

  • 若复制对象数组,那么只是复制了对象的引用,而不是对象本身的拷贝;

  • 这两个方法不会执行自动包装和自动拆包,所以两个数组必须具有相同的确切类型。


2、数组的字符串方式表示

方法: Arrays.toString(Object[] a) / Arrays.deepToString(Object[] a)

作用: 返回指定数组内容的字符串表示形式:前者适用于一维数组,或者适用于多维数组


3、数组的比较

方法: Arrays.equals(Object[] a, Object[] a2)  /   deepEquals(Object[] a1, Object[] a2) (多维)

作用: 比较两个数组:元素类型相同,元素个数相等,对应位置的元素相同;

注意:

  • 通过对每个元素使用 equals() 作比较来判断;

  • 对于基本类型,使用的是基本类型的包装器类的 equals() 方法(对于 int 类型使用 Integer.equals() 作比较);

  • 使用 equals() 方法比较原则:是不是同一个对象,是不是同一个类型,是不是具有相同的内容。

int[] a1 = new int[10]; 
int[] a2 = new int[10]; 
Arrays.fill(a1, 47); 
Arrays.fill(a2, 47); 
print(Arrays.equals(a1, a2));    //true

4、数组的排序

  使用内置的排序方法,就可以对任意的基本类型数组排序;也可以对任意的对象数组进行排序,只要该对象实现了 Comparable 接口或具有相关联的 Comparator (独立的实现该接口的类)。

方法: Arrays.sort(Object[] a) / Arrays.sort(Object[] a, int fromIndex, int toIndex)  
   Arrays.sort(T[] a, Comparatorafdb413486077de11f19a9eac0d8049c c) / Arrays.sort(T[] a, int fromIndex, int toIndex, Comparator117c5a0bdb71ea9a9d0c2b99b03abe3e c)

作用: 对数组内元素进行升序排序 (默认)

String[] sa = Generated.array(new String[20], new RandomGenerator.String(5)); 

// 利用 String 内置的比较器(已实现 Comparable 接口):字典序(大写字母开头的词都放在前面输出,之后才是小写字母开头的词)Arrays.sort(sa);   
// ... ,WHkjU, YNzbr, bkIna, cQrGs, ....
// 利用 Comparator 比较 : Collections.reverseOrder() : 现有顺序的逆序Arrays.sort(sa, Collections.reverseOrder()); 

// 利用 Comparator 比较 : String.CASE_INSENSITIVE_ORDER : 忽略大小写将单词一起进行排序Arrays.sort(sa, String.CASE_INSENSITIVE_ORDER);

  Java 标准类库中的排序算法针对正排序的特殊类型进行了优化 ———— 针对基本类型设计的“快排” 和 针对对象设计的“稳定归并排序”。所以,无需担心排序的性能,除非你可以证明排序部分的确是程序效率的瓶颈。


5、在已排序的数组中查找

  若数组已经 排好序,就可以使用该方法执行快速查找;若对未排序的数组使用该方法,将产生不可预料的结果。

方法: binarySearch(Object[] a, Object key) / binarySearch(T[] a, T key, Comparator117c5a0bdb71ea9a9d0c2b99b03abe3e c)

作用: 使用 二分搜索来搜索指定数组,以获得指定对象。在进行此调用之前,必须根据元素的自然顺序对数组进升序排序(通过 sort(Object[]) 方法); 使用二分搜索法来搜索指定数组,以获得指定对象。在进行此调用之前,必须根据指定的比较器(通过 sort(T[], Comparator) 方法)对数组进行多态升序排序

注意:

  • 已经有序 的数组进行查找;

  • If the target is found, the value returned by the method is not less than 0; otherwise, the negative return value it generates indicates the position that should be inserted under this sorting;

  • "sort(Object[])" corresponds to "binarySearch(Object[] a, Object key)", "sort(T[], Comparator)" corresponds to binarySearch(T[] a, T key, Comparator117c5a0bdb71ea9a9d0c2b99b03abe3e c) Corresponds.

     If the array contains duplicate elements, this method cannot guarantee which element is found; if you need to sort an array without duplicate elements, you can use Tree Set(maintain sorting order) or LinkedHashSet(maintain insertion order) to sort. There is no need to maintain arrays yourself unless they become a bottleneck in your program.


6. Fill array

Method: fill(Object[] a, Object val)
Function: You can only use the same value to fill each position, and for objects, it is to copy the reference of the same object to fill it


7. Conversion between arrays and containers

Method: asList(T... a)
Function: Returns a Fixed size list supported by the specified array
Note:

  • The resulting List is fixed size because The underlying representation is the array, so it cannot be resized. Therefore, calling the add/remove method will throw java.lang.UnsupportedOperationException (optional operation).

  • So, Arrays.asList() is really all about: passing its result as a constructor argument to any Collection (or using addAll method, Collections.addAll staticmethod), this can generate a dynamic container.


## 7. Summary

Principle:

  • Prefer to use containers instead of arrays;

  • Use arrays and variable parameters When making method parameters, prioritizing the use of variable parameters will make the program more decoupled;

  • The practical functions of the Arrays tool class will make us Get twice the result with half the effort in programming.

以上是Java 數組程式碼實例綜述的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn