跳過 Java 中的第一次迭代
一、簡介
迭代是程式設計的基石,使開發人員能夠遍歷並輕鬆操作資料結構。但是,在某些情況下,我們可能需要在跳過第一個元素的同時迭代這些集合。在本教程中,我們將探索使用循環和 Stream API 跳過第一個元素的各種方法。
2. 跳過第一個元素
在 Java 中迭代集合時,有多種方法可以跳過第一個元素。下面,我們介紹三種主要方法:使用標準迴圈、使用Iterator
介面和利用 Stream API。
某些演算法出於不同原因需要跳過第一個元素:單獨處理它或完全跳過它,例如 CSV 標頭。計算小型企業每日收入之間的運作差異可能是這種方法的一個很好的例子:
從第二個元素開始迭代可以幫助我們創建一個簡單的演算法,並使我們免於不必要和不直觀的檢查。
2.1. For循環
跳過第一個元素的最簡單方法是使用for
循環並從 1 而不是 0 開始計數器變數。這種方法最適合支援索引存取的集合,例如ArrayList
和簡單數組:
void skippingFirstElementInListWithForLoop(List<String> stringList) {
for (int i = 1; i < stringList.size(); i++) {
process(stringList.get(i));
}
}
這種方法的主要好處是它的簡單性。此外,如果我們願意的話,它允許我們存取第一個值。同時,初始值的設定也很容易被忽略。
2.2. While 循環
另一種方法是使用while
迴圈和Iterator
。我們可以手動推進迭代器以跳過第一個元素:
void skippingFirstElementInListWithWhileLoop(List<String> stringList) {
Iterator<String> iterator = stringList.iterator();
if (iterator.hasNext()) {
iterator.next();
}
while (iterator.hasNext()) {
process(iterator.next());
}
}
此方法的好處之一是它適用於所有Iterable
集合,例如Set
:
void skippingFirstElementInSetWithWhileLoop(Set<String> stringSet) {
Iterator<String> iterator = stringSet.iterator();
if (iterator.hasNext()) {
iterator.next();
}
while (iterator.hasNext()) {
process(iterator.next());
}
}
另一個好處是我們可以將集合抽象化為最通用的類別;在這種情況下,它將是Iterable
並重複使用程式碼。然而,由於Sets
在大多數情況下沒有順序的概念,因此不清楚我們將跳過哪個元素。另一方面,如果我們需要第一個元素,我們必須明確地儲存它:
void skippingFirstElementInListWithWhileLoopStoringFirstElement(List<String> stringList) {
Iterator<String> iterator = stringList.iterator();
String firstElement = null;
if (iterator.hasNext()) {
firstElement = iterator.next();
}
while (iterator.hasNext()) {
process(iterator.next());
// additional logic using fistElement
}
}
2.3.串流媒體介面
Java 8 引入了 Stream API,它提供了一種更具聲明性的方式來操作集合。要跳過第一個元素,我們可以使用skip()
方法:
void skippingFirstElementInListWithStreamSkip(List<String> stringList) {
stringList.stream().skip(1).forEach(this::process);
}
與前一個方法一樣,此方法適用於 Iterable 集合,且其意圖非常詳細。我們可以透過這種方法輕鬆使用Set
:
void skippingFirstElementInSetWithStreamSkip(Set<String> stringSet) {
stringSet.stream().skip(1).forEach(this::process);
}
另外,我們可以使用Map
:
void skippingFirstElementInMapWithStreamSkip(Map<String, String> stringMap) {
stringMap.entrySet().stream().skip(1).forEach(this::process);
}
Maps
與Sets
類似,不維護元素的順序,因此請謹慎使用,因為在這種情況下第一個元素沒有明確定義。但是,有時跳過Set
或Map
中的元素可能很有用。
2.4.使用subList()
跳過Lists
中第一個元素的另一種方法是使用subList()
方法。此方法傳回指定的fromIndex
(包含)和toIndex
(不包含)之間的清單部分的視圖。當我們將其與for-each
循環配對時,我們可以輕鬆跳過第一個元素:
void skippingFirstElementInListWithSubList(List<String> stringList) {
for (final String element : stringList.subList(1, stringList.size())) {
process(element);
}
}
問題之一是subList()
在空列表上可能會失敗。另一件事是,不清楚它不會創建一個單獨的集合並提供原始集合的視圖,特別是對於剛接觸 Java 的人來說。總的來說,這是一種非常必要的迭代方式。
2.5.其他方法
儘管迭代集合的基本方法只有少數,但我們可以組合和更改它們以獲得更多變化。由於這些變化並沒有本質上的不同,我們在這裡列出它們以展示可能的方法並啟發實驗。
我們可以使用附加if
語句的for
迴圈來跳過第一個元素。當我們需要將第一個元素與其他元素分開處理時,它很有用:
void skippingFirstElementInListWithForLoopWithAdditionalCheck(List<String> stringList) {
for (int i = 0; i < stringList.size(); i++) {
if (i == 0) {
// do something else
} else {
process(stringList.get(i));
}
}
}
我們可以將for
迴圈中使用的邏輯應用到while
循環中,並在其中使用計數器:
void skippingFirstElementInListWithWhileLoopWithCounter(List<String> stringList) {
int counter = 0;
while (counter < stringList.size()) {
if (counter != 0) {
process(stringList.get(counter));
}
++counter;
}
}
當我們需要根據某些內部邏輯以不同的步驟推進清單時,這種方法可能會很有幫助。
此外,我們可以將該方法與subList
和stream
結合:
void skippingFirstElementInListWithStreamSkipAndSubList(List<String> stringList) {
stringList.subList(1, stringList.size()).forEach(this::process);
}
總的來說,我們的想像可以讓我們做出一些根本不該使用的深奧決定:
void skippingFirstElementInListWithReduce(List<String> stringList) {
stringList.stream().reduce((skip, element) -> {
process(element);
return element;
});
}
三、結論
雖然 Java 提供了不同的方法來迭代集合,同時跳過第一個元素,但選擇正確方法的主要指標是程式碼的清晰度。**因此,我們應該選擇兩個簡單且最冗長的方法,即簡單的for
循環或stream.skip().
**其他方法更複雜,包含更多移動部件,應盡可能避免。
與往常一樣,本文中的範例可以在 GitHub 上找到。