HOWTO · Java
在 Java 中建立子陣列
本教程將演示如何在 Java 中從另一個陣列建立子陣列
本頁內容
子陣列是將一段連續範圍複製到另一個陣列。Java 陣列使用從 0 開始的索引:起始索引包含在範圍內,結束索引則指向最後一個複製元素之後的位置。以下範例會從來源陣列複製索引 1 到 3 的元素。
Java 中子陣列的意義
複製一段範圍會建立新陣列,而不是建立原陣列的檢視。因此,修改複製後的 int[] 中某個元素,不會改變來源陣列。若陣列存放的是物件,新陣列會包含相同的物件參考;因此,修改物件本身,仍可能透過任一陣列看見變化。
常見的範圍表示法是 [start, end):包含 start,但不包含 end。若來源陣列有九個元素,索引範圍是 0 到 8。從索引 2 到 5 的範圍包含三個元素。將所需元素數量換算成結束索引時,請記住這項慣例:end 等於 start + length。
使用 Arrays.copyOfRange 建立子陣列
若要配置新陣列,Arrays.copyOfRange 是簡潔的選擇。依序傳入來源陣列、包含在範圍內的起始索引,以及不包含在範圍內的結束索引。執行以下範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import java.util.Arrays;
public class SubarrayExample {
public static void main(String[] args) {
int[] source = {10, 20, 30, 40, 50, 60};
int[] part = Arrays.copyOfRange(source, 1, 4);
System.out.println(Arrays.toString(part));
}
}
[20, 30, 40]
結果是另一個陣列,其中包含來源陣列索引 1、2 和 3 的元素。結束索引所指的位置不會複製。允許指定超出來源陣列長度的結束索引,結果會以元素型別的預設值補齊(0 適用於 int,null 適用於參考型別)。起始索引必須位於來源陣列範圍內,或等於陣列長度;結束索引不得小於起始索引。如果希望結束索引超出來源長度時改為報錯,請在呼叫方法前先進行驗證。
使用 System.arraycopy 建立子陣列
若需要自行指定目標陣列或插入位置,請使用 System.arraycopy。它的五個引數依序是來源陣列、來源位置、目標陣列、目標位置,以及元素數量。最後一個引數是元素數量,不是結束索引;從目標位置開始,目標陣列必須有足夠空間容納指定數量的元素。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import java.util.Arrays;
public class SubarrayWithArraycopy {
public static void main(String[] args) {
int[] source = {10, 20, 30, 40, 50, 60};
int start = 1;
int length = 3;
int[] part = new int[length];
System.arraycopy(source, start, part, 0, length);
System.out.println(Arrays.toString(part));
}
}
此處複製範圍會在 start + length 處結束,也就是索引 4;該索引不包含在範圍內。請依預定複製的元素數量配置目標陣列。Java 會檢查位置和長度;若參考型別陣列的元素型別不相容,也可能發生陣列儲存錯誤。
使用迴圈建立子陣列
使用迴圈可以明確指定目標陣列的偏移量,也能在複製時檢查或轉換每個元素。對於 [start, end) 範圍,目標索引 i - start 會從 0 開始,並隨來源索引逐步增加。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import java.util.Arrays;
public class SubarrayWithLoop {
public static void main(String[] args) {
int[] source = {10, 20, 30, 40, 50, 60};
int start = 1;
int end = 4;
int[] part = new int[end - start];
for (int i = start; i < end; i++) {
part[i - start] = source[i];
}
System.out.println(Arrays.toString(part));
}
}
此迴圈假設索引指定的是來源陣列中的有效範圍。如果索引來自使用者輸入,請在配置陣列前先檢查。與 Arrays.copyOfRange 不同,當指定的結束索引超出來源陣列時,迴圈不會自動補值;存取超出範圍的索引會失敗。若複製時還需要套用條件、轉換或其他自訂規則,迴圈就很實用。
使用 Stream API 建立子陣列
對 int[] 而言,IntStream.range(start, end) 會產生從起始索引(包含)到結束索引(不包含)之間的索引。將每個索引對應到來源陣列中的值,再使用 toArray() 將這些值收集到新的基本型別陣列中。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import java.util.Arrays;
import java.util.stream.IntStream;
public class SubarrayWithStream {
public static void main(String[] args) {
int[] source = {10, 20, 30, 40, 50, 60};
int[] part = IntStream.range(1, 4)
.map(i -> source[i])
.toArray();
System.out.println(Arrays.toString(part));
}
}
這裡使用的範圍慣例與前面的範例相同。串流產生的索引仍須是來源陣列中的有效索引。如果你想直接用索引管線表達元素選取方式,可以採用這個方法;串流本身並不會讓範圍驗證變得多餘。
依使用情境選擇方法
若要直接配置新陣列並複製一段範圍,請選擇 Arrays.copyOfRange,尤其是需要使用其結束位置超出來源陣列時的補值行為。若已經有目標陣列,或需要從非零的目標位置開始放入複製的值,請選擇 System.arraycopy。若複製時需要逐一處理元素,請使用迴圈。若將索引轉換組合成串流管線能讓程式碼更易讀,則可選用 Stream API。
Arrays.copyOfRange、迴圈和 Stream API 範例都會配置新陣列。System.arraycopy 會將元素複製到你提供的目標陣列中;只有在你為此配置目標陣列時,才會建立新的容器。對基本型別陣列而言,複製的是值;對物件陣列而言,複製的是參考,而不是參考所指向的物件本身。請依所需的範圍行為、目標陣列控制方式及額外處理需求選擇方法;這些範例不比較效能。