將 Java 掃描器輸入存儲在數組中
一、概述
在 Java 中,從Scanner
對象讀取輸入是很常見的。此外,輸入通常存儲在數組中以供進一步處理。
在本教程中,我們將探討如何使用 Java 將掃描儀輸入保存在數組中。
二、問題介紹
當我們將來自Scanner
輸入存儲為數組時,可能存在三種情況:
- 單行輸入——每個標記都是一個數組元素。
- 多行輸入——每一行都是一個數組元素。
- 多行輸入——每行的每個標記都是一個數組元素。
我們將在本教程中討論這些案例。此外,為簡單起見,我們將通過字符串提供給Scanner
對象,並使用單元測試斷言來驗證我們是否獲得了預期的結果。
3.單行輸入:每個令牌一個數組元素
首先,假設一個Scanner
對像有這個輸入:
String input = "Java Kotlin Ruby Python Go\n";
正如我們所見,輸入行有五個標記。因此,結果數組應如下所示:
String[] expected = new String[] { "Java", "Kotlin", "Ruby", "Python", "Go" };
Java Scanner
的默認分隔符是空格。此外, Scanner.next()
允許我們從輸入中讀取下一個標記。因此,我們可以循環調用next()
方法來填充一個數組:
Scanner scanner1 = new Scanner(input);
String[] result1 = new String[5];
int i = 0;
while (i < result1.length) {
result1[i] = scanner1.next();
i++;
}
assertArrayEquals(expected, result1);
眼尖的人可能已經註意到,這個解決方案只適用於一行中有五個標記的情況,因為我們定義了數組的容量 ( 5
) 。這是因為Java 數組是固定大小的。所以,我們需要在實例化的時候設置它的大小。
顯然,當我們不知道輸入中有多少元素時,這種方法就不那麼方便了。
或者,我們可以使用Scanner.nextLine()
方法讀取整個輸入行,並將該行split()
成一個數組:
Scanner scanner2 = new Scanner(input);
String[] result2 = scanner2.nextLine().split("\\s+");
assertArrayEquals(expected, result2);
4.多行輸入:每行一個數組元素
接下來,讓我們構建一個多行輸入:
String input = new StringBuilder().append("Baeldung Java\n")
.append("Baeldung Kotlin\n")
.append("Baeldung Linux\n")
.toString();
然後,我們期望輸入中的每一行成為結果數組中的一個元素:
String[] expected = new String[] {"Baeldung Java", "Baeldung Kotlin", "Baeldung Linux"};
我們可以調用Scanner.nextLine()
來讀取輸入行並在循環中填充數組:
String[] result = new String[3];
Scanner scanner = new Scanner(input);
int i = 0;
while (i < result.length) {
result[i] = scanner.nextLine();
i++;
}
assertArrayEquals(expected, result);
同樣,我們在上面的代碼中聲明數組對象時設置了大小 ( 3
)。
由於List
具有動態大小,如果我們不知道輸入中的行數,我們可以使用List
來存儲行:
List<String> expected = Lists.newArrayList("Baeldung Java", "Baeldung Kotlin", "Baeldung Linux");
List<String> result = new ArrayList<>();
Scanner scanner = new Scanner(input);
while (scanner.hasNextLine()) {
result.add(scanner.nextLine());
}
assertEquals(expected, result);
當然,如果我們最終的結果必須是一個數組,我們可以很方便地將結果List
轉為數組。
5. 多行輸入:每個標記一個數組元素
現在,讓我們看看如何將來自多行輸入的標記存儲在數組中。假設我們有這樣的兩行輸入:
String input = new StringBuilder().append("Linux Windows MacOS\n")
.append("Java Kotlin Python Go\n")
.toString();
我們想要一個包含這些元素的數組:
String[] expected = new String[] { "Linux", "Windows", "MacOS", "Java", "Kotlin", "Python", "Go" };
為了解決這個問題,我們可以使用Scanner.nextLine()
和split()
將每一行讀取到一個數組中。此外,我們需要將這個數組與最終結果數組合併。
接下來,讓我們看看它是如何工作的:
String[] result = new String[] {};
Scanner scanner = new Scanner(input);
while (scanner.hasNextLine()) {
String[] lineInArray = scanner.nextLine().split("\\s+");
result = ObjectArrays.concat(result, lineInArray, String.class);
}
assertArrayEquals(expected, result);
在上面的測試中,為了簡單起見,我們使用了 Guava 的ObjectArrays.concat()
來連接兩個數組。
但是,連接數組會創建一個新數組並將兩個數組複製到新數組中。因此,這種方法可能很慢,尤其是當我們有大量輸入行時。
為了獲得更好的性能,我們可以使用List
來存儲標記:
List<String> expected = Lists.newArrayList("Linux", "Windows", "MacOS", "Java", "Kotlin", "Python", "Go");
List<String> result = new ArrayList<>();
Scanner scanner = new Scanner(input);
while (scanner.hasNext()) {
result.add(scanner.next());
}
assertEquals(expected, result);
同樣,如果需要,我們可以將列表結果轉換為數組。
6. 關於數組與List
一個詞
當我們逐步了解解決問題的方法時,我們可能已經意識到將輸入存儲到List
中比數組更靈活。除了動態大小屬性外,列表與數組相比還有其他優點,例如:
- 易於添加和刪除元素
- 類型安全
- 方便的內置操作,例如
indexOf(), contains()
等 - 各種實現,例如
ArrayList
、LinkedList,
等
因此,我們在做Java項目時,應該考慮使用列表而不是數組。
七、結論
在本文中,我們學習瞭如何將Scanner
的輸入存儲到數組中。
此外,我們還討論了三種不同的場景,並通過示例探索了每種解決方案。
與往常一樣,此處提供的所有代碼片段都可以在 GitHub 上找到。