# 用Java學資料結構-Array
這是我的資料結構學習筆記的第一篇,所以先來了解一些基礎知識,然後再進入 Array 的部分。
資料結構可以用來處理基礎型別(Primitive Type)和物件(Object)。基礎型別有以下幾種:
- Integer
- Float
- Double
- Char
- Boolean
- String
- Byte
- Short
## 什麼是 Array
- Array 是一種資料結構
- 用來儲存相同型別的元素
- Array 的元素是有序的
- 並且可以透過索引(index)來存取
- Array 的大小是固定的
- 在建立 Array 時,必須指定 Array 的大小
## Array 的基礎
如果要用城市來記錄 5 個城市的名稱,只用變數的方式,需要定義 5 個變數,如下:
```java
String city1 = "台北";
String city2 = "台中";
String city3 = "高雄";
String city4 = "台南";
String city5 = "花蓮";
```
但這樣一個一個定義變數,不僅麻煩,而且不容易管理。這時可以使用陣列來解決這個問題。
```java
String[] cities = new String[5];
cities[0] = "台北";
cities[1] = "台中";
cities[2] = "高雄";
cities[3] = "台南";
// 也可以這樣初始化
String[] cities = {"台北", "台中", "高雄", "台南", "花蓮"};
```
> 陣列的索引是從 0 開始的。
如果你想要取出陣列中的元素,可以使用陣列的索引值,如下:
```java
System.out.println(cities[0]); // 台北
System.out.println(cities[1]); // 台中
System.out.println(cities[2]); // 高雄
System.out.println(cities[3]); // 台南
System.out.println(cities[4]); // 花蓮
```
如果你想要知道陣列的長度,可以使用 `length` 屬性,如下:
```java
System.out.println(cities.length); // 5
```
在 JDK 5 之前,如果想要迭代陣列,只能使用 `for` 迴圈,如下:
```java
for (int i = 0; i < cities.length; i++) {
System.out.println(cities[i]);
}
```
在 JDK 5 之後,Java 提供了 `foreach` 迴圈,可以更簡潔地迭代陣列,如下:
```java
for (String city : cities) {
System.out.println(city);
}
```
## 多維陣列
多維陣列是指陣列中的元素也是陣列。例如,如果要用城市來記錄 5 個城市的名稱和人口,可以使用二維陣列,如下:
```java
String[][] cities = {
{"台北", "300 萬"},
{"台中", "200 萬"},
{"高雄", "150 萬"},
{"台南", "100 萬"},
{"花蓮", "50 萬"}
};
```
如果你想要取出二維陣列中的元素,可以使用兩個索引值,如下:
```java
System.out.println(cities[0][0]); // 台北
System.out.println(cities[0][1]); // 300 萬
System.out.println(cities[1]); // {台中, 200 萬}
```
## 陣列的常用方法與操作
Java 提供了一些常用的方法來操作陣列,如下:
- `Arrays.toString()`:將陣列轉換為字串。
- `Arrays.sort()`:將陣列排序,預設是升冪排序。也就是從小到大排序。
- `Arrays.reverse()`:將陣列反轉。也就是將陣列的元素順序反轉。
- `Arrays.binarySearch()`:在排序後的陣列中查找元素。
```java
int[] numbers = {5, 3, 8, 1, 2};
System.out.println(Arrays.toString(numbers)); // [5, 3, 8, 1, 2]
Arrays.sort(numbers);
System.out.println(Arrays.toString(numbers)); // [1, 2, 3, 5, 8]
int index = Arrays.binarySearch(numbers, 3);
System.out.println(index); // 2
Arrays.reverse(numbers);
System.out.println(Arrays.toString(numbers)); // [8, 5, 3, 2, 1]
```
- `Arrays.fill()`:填充陣列。
```java
int[] numbers = new int[5];
Arrays.fill(numbers, 5);
System.out.println(Arrays.toString(numbers)); // [5, 5, 5, 5, 5]
```
- `Arrays.copyOf()`:複製陣列。使用這個複製的方法,他們的參考地址是不一樣的。
```java
int[] numbers1 = {1, 2, 3, 4, 5};
int[] numbers2 = numbers1;
int[] numbers3 = Arrays.copyOf(numbers1, numbers1.length);
numbers1[0] = 0;
System.out.println(Arrays.toString(numbers1)); // [0, 2, 3, 4, 5]
System.out.println(Arrays.toString(numbers2)); // [0, 2, 3, 4, 5]
System.out.println(Arrays.toString(numbers3)); // [1, 2, 3, 4, 5]
System.out.println(numbers1 == numbers2); // true
System.out.println(numbers1 == numbers3); // false
System.out.println(numbers2 == numbers3); // false
```
> 當你一宣告一個陣列時,實際上是在記憶體中開辟了一塊連續的空間(長度),這個長度是固定的,不能改變。如果你想要改變陣列的長度,只能重新宣告一個新的陣列,然後將舊的陣列複製到新的陣列中。
## 淺拷貝與深拷貝
在 Java 中,陣列是一種物件,當你將一個陣列賦值給另一個陣列時,實際上是將陣列的參考地址賦值給另一個陣列,這稱為淺拷貝。也就是說,兩個陣列共享同一個記憶體空間,當一個陣列改變時,另一個陣列也會改變。
```java
int[] numbers1 = {1, 2, 3, 4, 5};
int[] numbers2 = numbers1;
numbers1[0] = 0;
System.out.println(Arrays.toString(numbers1)); // [0, 2, 3, 4, 5]
System.out.println(Arrays.toString(numbers2)); // [0, 2, 3, 4, 5]
System.out.println(numbers1 == numbers2); // true, 兩個陣列的參考地址是一樣的
```
如果你想要深拷貝一個陣列,可以使用 `Arrays.copyOf()` 方法,如下:
```java
int[] numbers1 = {1, 2, 3, 4, 5};
int[] numbers2 = Arrays.copyOf(numbers1, numbers1.length);
numbers1[0] = 0;
System.out.println(Arrays.toString(numbers1)); // [0, 2, 3, 4, 5]
System.out.println(Arrays.toString(numbers2)); // [1, 2, 3, 4, 5]
System.out.println(numbers1 == numbers2); // false, 兩個陣列的參考地址是不一樣的
```