1. Introduction
1.导言
Iterating is a cornerstone of programming, enabling developers to traverse and easily manipulate data structures. However, there are situations where we may need to iterate over these collections while skipping the first element. In this tutorial, we’ll explore various methods to skip the first element using loops and the Stream API.
迭代是编程的基石,它使开发人员能够遍历并轻松操作数据结构。然而,在某些情况下,我们可能需要遍历这些集合,同时跳过第一个元素。在本教程中,我们将探索使用循环和 Stream API 跳过第一个元素的各种方法。
2. Skipping the First Element
2.跳过第一个要素
There are various ways to skip the first element in Java when iterating through a collection. Below, we cover three major approaches: using standard loops, using the Iterator interface, and utilizing the Stream API.
在 Java 中,有多种方法可以在遍历集合时跳过第一个元素。下面,我们将介绍三种主要方法:使用标准循环、使用 Iterator 接口和使用流 API。
Some algorithms require skipping the first element for different reasons: to process it separately or skip it entirely, for example, CSV headers. Calculating running differences between the daily income of a small business might be a good example of this approach:
有些算法出于不同原因需要跳过第一个元素:单独处理或完全跳过,例如 CSV 头。计算一个小企业每日收入的运行差异可能就是这种方法的一个很好的例子:
Iterating from the second element helps us to create a simple algorithm and saves us from unnecessary and non-intuitive checks.
从第二个元素开始迭代,可以帮助我们创建一个简单的算法,避免不必要的、非直观的检查。
2.1. For Loop
2.1.循环
The simplest way to skip the first element is to use a for loop and start the counter variable from 1 instead of 0. This approach is most suitable for collections that support indexed access, like ArrayList and simple arrays:
跳过第一个元素的最简单方法是使用 for 循环,并从 1 而不是 0 开始计数变量。 这种方法最适合支持索引访问的集合,如 ArrayList 和简单数组:
void skippingFirstElementInListWithForLoop(List<String> stringList) {
for (int i = 1; i < stringList.size(); i++) {
process(stringList.get(i));
}
}
The main benefit of this approach is its simplicity. Also, it allows us to access the first value if we would like to do so. At the same time, setting the initial value might be easily overlooked.
这种方法的主要优点是简单。此外,如果我们想访问第一个值,它还允许我们这样做。同时,设置初始值可能很容易被忽略。
2.2. While Loop
2.2.While 循环
Another way is to use a while loop along with an Iterator. We can manually advance the iterator to skip the first element:
另一种方法是使用 while 循环和 Iterator 。我们可以手动推进迭代器以跳过第一个元素:
void skippingFirstElementInListWithWhileLoop(List<String> stringList) {
Iterator<String> iterator = stringList.iterator();
if (iterator.hasNext()) {
iterator.next();
}
while (iterator.hasNext()) {
process(iterator.next());
}
}
One of the benefits of this method is the fact that it works with all the Iterable collections, such as Set:
该方法的优点之一是它可与所有Iterable集合(如Set)配合使用:
void skippingFirstElementInSetWithWhileLoop(Set<String> stringSet) {
Iterator<String> iterator = stringSet.iterator();
if (iterator.hasNext()) {
iterator.next();
}
while (iterator.hasNext()) {
process(iterator.next());
}
}
An additional benefit is that we can abstract the collection to the most general class; in this case, it would be Iterable and reuse the code. However, as Sets, in most cases, don’t have the notion of order, it’s not clear which element we’ll skip. On the other side, if we need the first element, we have to store it explicitly:
另一个好处是,我们可以将集合抽象为最通用的类;在本例中,它将是 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. Stream API
2.3.流应用程序接口
Java 8 introduced the Stream API, which provides a more declarative way to manipulate collections. To skip the first element, we can use the skip() method:
<要跳过第一个元素,我们可以使用 skip() 方法:
void skippingFirstElementInListWithStreamSkip(List<String> stringList) {
stringList.stream().skip(1).forEach(this::process);
}
Like the previous one, this method works on Iterable collection and is quite verbose about its intentions. We can easily use Set with this approach:
与前一种方法一样,这种方法也适用于 Iterable 集合,而且其意图非常啰嗦。我们可以用这种方法轻松地使用 Set :
void skippingFirstElementInSetWithStreamSkip(Set<String> stringSet) {
stringSet.stream().skip(1).forEach(this::process);
}
Also, we can use a Map:
此外,我们还可以使用 Map:
void skippingFirstElementInMapWithStreamSkip(Map<String, String> stringMap) {
stringMap.entrySet().stream().skip(1).forEach(this::process);
}
Maps, similar to Sets, don’t maintain the order of the elements, so please use this with caution, as the first element isn’t clearly defined in this case. However, sometimes skipping an element in a Set or in a Map might be useful.
映射与集合类似,并不保持元素的顺序,因此请谨慎使用,因为在这种情况下,第一个元素并没有明确定义。不过,有时跳过 Set 或Map中的某个元素可能会很有用。
2.4. Using subList()
2.4.使用 subList()
Another way to skip the first element in Lists is using the subList() method. This method returns a view of the portion of the list between the specified fromIndex, inclusive, and toIndex, exclusive. When we pair this with a for-each loop, we can easily skip the first element:
跳过 Lists 中第一个元素的另一种方法是使用 subList() 方法。该方法返回指定的 fromIndex (含)和 toIndex (不含)之间的列表部分的视图。当我们将该方法与 for-each 循环搭配使用时,可以轻松跳过第一个元素:
void skippingFirstElementInListWithSubList(List<String> stringList) {
for (final String element : stringList.subList(1, stringList.size())) {
process(element);
}
}
One of the issues is that subList() can fail on empty lists. Another thing is that it’s not clear, especially for people new to Java, that it doesn’t create a separate collection and provides a view of the original one. Overall, this is a highly imperative way of iterating.
其中一个问题是,subList() 可能会在空列表上失败。另一个问题是,尤其是对于 Java 新手来说,他们并不清楚 subList() 并没有创建一个单独的集合,而是提供了对原始集合的查看。总的来说,这是一种高度perative的迭代方式。
2.5. Other Methods
2.5.其他方法
Although there are only a handful of fundamental ways to iterate over a collection, we could combine and alter them to get more variations. As these variations aren’t substantially different, we list them here to show possible approaches and inspire experimentation.
虽然对集合进行迭代的基本方法屈指可数,但我们可以将它们组合起来并加以改变,以获得更多的变化。由于这些变化并无本质区别,我们在此列出这些变化,以展示可能的方法并激发实验热情。
We can skip the first element using a for loop with an additional if statement. It’s useful when we need to process the first element separately from the others:
我们可以使用带有附加 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));
}
}
}
We can apply the logic we’re using in a for loop to a while loop and use a counter inside it:
我们可以将 for 循环中的逻辑应用到 while 循环中,并在其中使用计数器:
void skippingFirstElementInListWithWhileLoopWithCounter(List<String> stringList) {
int counter = 0;
while (counter < stringList.size()) {
if (counter != 0) {
process(stringList.get(counter));
}
++counter;
}
}
This approach might be helpful when we need to advance the list in different steps depending on some internal logic.
当我们需要根据某些内部逻辑以不同步骤推进列表时,这种方法可能会有所帮助。
Also, we can combine the approach with subList and with stream:
此外,我们还可以将这种方法与 subList 和 stream 结合起来:
void skippingFirstElementInListWithStreamSkipAndSubList(List<String> stringList) {
stringList.subList(1, stringList.size()).forEach(this::process);
}
Overall, our imagination can bring us to some esoteric decisions that should not be used at all:
总的来说,我们的想象力会让我们做出一些根本不应该使用的深奥决定:
void skippingFirstElementInListWithReduce(List<String> stringList) {
stringList.stream().reduce((skip, element) -> {
process(element);
return element;
});
}
3. Conclusion
3.结论
While Java offers different ways to iterate a collection while skipping the first element, the primary metric in picking the right approach is the clarity of the code. Thus, we should opt for two simple and the most verbose methods, which are simple for loop or stream.skip(). Other methods are more complex, contain more moving parts, and should be avoided if possible.
虽然 Java 提供了不同的方法来遍历集合,同时跳过第一个元素,但选择正确方法的首要标准是代码的清晰度。因此,我们应选择两种简单且最冗长的方法,即简单的 for 循环或 stream.skip()。其他方法更为复杂,包含更多活动部件,应尽可能避免使用。
As usual, the examples from this article are available over on GitHub.
与往常一样,本文中的示例可在 GitHub 上获取。