2018年11月1日 星期四

Java SE 入門教學 - 陣列

更新時間:11/01/2018

前言

如果要管理一個班級的成績,班級人數有30人,那麼我需要建立30個名字變數,30個國文成績,30個數學成績,30個英文成績等等...,光是宣告變數就要上百個,那...我需要怎麼管理程式?!

一、陣列的基本概念

陣列可以看成是多個相同類型數據組合,對這些數據的統一管理,數據類型可以是「基本型態」或「類別型態」。

陣列的元素起始位置從 0 開始,依序遞增(0, 1, 2, ...)。

二、一維陣列

JAVA 正規宣告陣列的方式與 C 語言完全不同,但後來也有加入一些宣告語法是仿 C 語言的。

2.1 一維陣列變數宣告

◉ 格式1:dataType[] arrayRefVar; (首選)

int[] a;
String[] str;

◉ 格式2:dataType arrayRefVar[]; (一樣可以作用,但非首選)

int a[];
String str[];

2.2 一維陣列建立

◉ 格式1:arrayRefVar = new dataType[arraySize];

a = new int[3];
str = new String[3];

◉ 格式2:arrayRefVar = new dataType[]{value0, value1, ..., valuek};

a = new int[]{10, -1, 0.5};
str = new String[]{"Hello", "JAVA", "!"};


陣列宣告與建立可以合併,例如:

int[] a = new int[3];
String[] str = new String[]{"JAVA", "is", "Object-Oriented", "Programming"};
double df[] = new []{2.2, -0.5, 3.14};

仿 C 的寫法,例如:

int[] a = {1, 2, 3};
int a[] = {3, 2, 1};


注意:JAVA 宣告陣列時,不能指定其長度,例如:

int a[5]; 這樣宣告一維陣列是非法的。

2.3 一維陣列記憶體配置狀況

◉ 宣告時,在 Stack 區建立一塊記憶體對應變數名字 a。
◉ 建立陣列時,在 Heap 區建立一塊足夠大的記憶體空間,並把記憶體頭的位址回存到 Stack 變數 a 的值。int 型態預設值為 0。
◉ 陣列賦值時,找到變數 a 對應的記憶體位址,映射到 Heap 區,並根據陣列的索引編號找到正確地址給予賦值。

三、二維陣列

JAVA 正規宣告陣列的方式與 C 語言完全不同,但後來也有加入一些宣告語法是仿 C 語言的。

3.1 二維陣列變數宣告

◉ 格式1:dataType[][] arrayRefVar; (首選)

int[][] a;
String[][] str;

◉ 格式2:dataType arrayRefVar[][]; (一樣可以作用,但非首選)

int a[][];
String str[][];

◉ 格式3:dataType[] arrayRefVar[]; (一樣可以作用,但非首選)
     中括號可以單獨擺在前面,也可以單獨擺在後面。

int[] a[];
String[] str[];

3.2 二維陣列建立

◉ 格式1:arrayRefVar = new dataType[arraySize][arraySize];

a = new int[2][3];
str = new String[2][3];

◉ 格式2:
  arrayRefVar = new dataType[][]{
          {value00, value01, ..., value0c},
          {value10, value11, ..., value1c},
           ... ,
          {valuer0, valuer1, ..., valuerc}
        };

a = new int[][]{{0,1,2}, {10,11,12}};
str = new String[][]{{"first", "row", "!"}, {"second", "row", "!!"}};


陣列宣告與建立可以合併,例如:

int[][] a = new int[2][3];
String[][] str = new String[][]{{"first", "row", "!"}, {"second", "row", "!!"}};
double[] df[] = new [][]{{0.1, 0.2, 0.3}, {1.1, 1.2, 1.3}};

仿 C 的寫法,例如:

int[][] a = {{0,1,2}, {10,11,12}};
int a[][] = {{0,1,2}, {10,11,12}};
int[] a[] = {{0,1,2}, {10,11,12}};


2.3 二維陣列記憶體配置狀況

◉ 宣告時,在 Stack 區建立一塊記憶體對應變數名字 a。
◉ 建立陣列時,在 Heap 區建立一塊足夠大的記憶體空間,並把記憶體頭的位址回存到 Stack 變數 a 的值。int 型態預設值為 0。
◉ 陣列賦值時,找到變數 a 對應的記憶體位址,映射到 Heap 區,並根據陣列的索引編號找到正確地址給予賦值。


2.4 二維不規則陣列

其實二維陣列可以看做是很多一維陣列組合起來。當建立陣列時,我可以一列一列建起來。如果每一列的長度都不一樣,那就會形成不規則的陣列了!宣告方式如下:

int[][] a = new int[3][];
int[] a[0] = new int[4];
int[] a[1] = new int[2];
int[] a[2] = new int[3];

或者

int[][] a = new int[][]{{10,20,30,40},{50,60},{90,100,110}};

四、一些陣列例子

◉ 簡單陣列的用法

建立陣列後,會以一個類別的形式產生,接著可以使用一些屬性或方法處理事情。

a.getClass().getName() 會獲取 a 陣列的類別名稱
a.length 會取得 a 陣列的長度
c.length 會取得 c 陣列的列(row)長度
c[0].lenght 會取得 c 陣列第一列的欄(column)長度


◉ 陣列加強版 for 迴圈(Enhanced For-Loops, foreach Loops)

把陣列元素一個一個拿出來存放在 refVar 裡。
語法(JDK 1.5 later):

for(dataType refVar : array){
  ...
}

Java API 裡有一個類別 Arrays,可以用來處理陣列相關事情。

◉ 骰子骰6000次,紀錄各點數出現的次數


不用 switch,也可以紀錄。

五、命令列引數(Command line argument)

在 Java 的程式進入點(Entry point),main()方法中必須撰寫 String[] args,這個 String 陣列的作用是讓您在啟動 Java 程式時,可以一併指定引數給 Java 程式來使用,例如若您的 Java 程式為 MyArray7 則您可以這麼執行 Java 程式:

$java MyArray7 param1 param2 ... paramk

Java 程式執行後,args[0] 將儲存 "param1" 字串,arg[1] 將儲存 "param2" 字串,...,arg[k-1] 將儲存 "paramk" 字串,啟動程式時您所提供的引數稱之為「命令列引數」,先簡單的示範如何將使用者提供的命令列引數接收後輸出。


您可以看到,在提供命令列引數給 Java 程式時,是以空白(white-space)作為分隔的依據,如果您打算提供一個內含空白的字串作為引數,則可以用雙引號來包括該字串。

命令列引數是以 String 物件儲存於 String 陣列 args 之中,如果您打算將之轉換為基本資料型態,則必須使用「包覆類別(wrapper class)」所提供的剖析方法:

基本型態 包覆類別 方法 說明
byte Byte Byte.parseByte(String s) 將 s 剖析為 byte 型態數值
short Short Short.parseShort(String s) 將 s 剖析為 short 型態數值
int Integer Integer.parseInt(String s) 將 s 剖析為 int 型態數值
long Long Long.parseLong(String s) 將 s 剖析為 long 型態數值
float Float Float.parseFloat(String s) 將 s 剖析為 float 型態數值
double Double Double.parseDouble(String s) 將 s 剖析為 double 型態數值

讀取命令列參數,並把字串轉成整數後相加。如果輸入的參數不是整數,則會拋出例外 java.lang.NumberFormatException

六、總結

陣列可以蒐集相同型態的數據,讓程式設計師可以良好的管理程式碼,並快速掌握資料。

盡量不使用二維陣列,其效能比一維陣列消耗得太多。
二維陣列可以使用一維陣列替代, arr2[i][j] 轉換成 arr1[i*columnSize + j]。

此篇文章帶出「物件」這個概念,但,什麼是「物件」?
這個概念很重要,我另開一篇好好談「物件」。





沒有留言:

張貼留言