preface
It has been a few months since I started Kotlin in April this year. In Kotlin, loop is a feature of this language. Recently, I used Canvas to do game development on Android, and I wrote a lot of loops, but I found it difficult to write multivariable For loop. I ended up either writing Kotlin calls in Java, or writing While loops. Today, I solved this pain point, so I decided to write an article about it.
The basic use
Let’s start with the simplest For loop before we get down to it
Loop from 0 to 100
Until the keyword
The until keyword requires a value on both the left and right side, and the until loop is a closed left open right interval
for (i in 0 until 100) {
println(i) // Output: 0 ~ 99
}
Copy the code
The final output contains 0 but not 100
Use..
. It also has a meaning in Kotlin. It’s called an interval expression, and it represents a left and right interval. Like the until keyword, both sides need a value when used
for (i in 0.100.) {
println(i) // Output: 0 ~ 100
}
Copy the code
The final output contains both 0 and 100
supplement
In fact.. The keyword can also be directly declared as a variable, which represents an interval. The variable will loop over the interval stored in it as it loops through
val test = 0.100.
Copy the code
Note: Use.. The created range must be in ascending order, that is, from small to large, not from large to small. You need to use another keyword “downTo” if you want to create a range from large to small
Loop from 100 to 0
DownTo keyword
Kotlin’s descending loop uses the keyword downTo, which also requires a value for both the left and right sides
for (i in 100 downTo 0) {
println(i) // Output: 100 ~ 0
}
Copy the code
You will suddenly realize why it is 100 ~ 0 and not 100 ~ 1. At the end of the keyword. The downTo keyword generates a left-closed and right-closed interval in terms of descending loops
Step keyword
Kotlin defaults to a step size of 1 for the loop. To change the step size, use the step keyword
Loop from 0 to 10 and set the step size to 2
for (i in 0.10. step 2) {
print("${if (i == 10) i else "$i-"}") // Output: 0--2--4--6--8--10
}
Copy the code
Looping array or list
So this is all about how you loop from one number to another, and a lot of times you loop by getting the values in a container like an ArrayList. The operation of looping these containers is simple in Kotlin
Loop through an array or list
For reasons of length, I will not post the code results here. Experts can try the following code by themselves
Define an array
val arrayList = arrayListOf(1.2.3.4.5.6.12.31.23.123.12.3.123.2)
Copy the code
Get the element out
for (i in arrayList) {
println(i) // output: 1,2,3,4.... 2
}
Copy the code
Loop through the index and elements
Fetching the element’s index at the same time requires calling the container’s withIndex() method during the loop
for ((index, item) in arrayList.withIndex()) {
println("index: $index, item: $item") // Output: index: 0, item: 1.... index: 13, item: 2
}
Copy the code
Iterate over an array or list by index
There are some cases where you can write it this way by traversing the index
for (i in 0 until arrayList.size) {
println(arrayList[i]) // output: 1,2,3,4.... 2
}
Copy the code
At this point you will find that your Idea will give you a yellow line warning because Kotlin’s case already provides you with an extension method indices
for (i in arrayList.indices) {
println(arrayList[i]) // output: 1,2,3,4.... 2
}
Copy the code
A little note
Kotlin’s for loop is actually much more than iterating through arrays or lists. It’s possible to iterate over any data container used in basic daily development (as long as the container implements the Iterable interface)
Multivariable cycle
Remember the pain point I mentioned in the introduction, which is the multivariable loop. Converting a multivariable for loop in Java to Kotlin directly translates to the syntax of while, but while leads to an explosion of lines of code, poor readability, and the creation of local variables.
Into each other
Take a look at the code for a Java multivariable for loop
// Java before conversion
for (int i = 0, j = 100; i < 100 && j > 0; i++, j--) {
System.out.println("i: " + i + ", j: " + j); I: 0, j: 100 ~ I: 99, j: 1
}
Copy the code
If you were to change this code to Kotlin’s for loop, what would you do? Not so fast, let’s turn into Kotlin and see what happens
// After conversion kotlin
var i = 0
var j = 100
while (i < 100 && j > 0) {
println("i: $i, j: $j") I: 0, j: 100 ~ I: 99, j: 1
i++
j--
}
Copy the code
Here Kotlin directly converts to while for us, and the downside of that has already been said, so I don’t need to go over it. Go straight to Kotlin for’s code
for ((i, j) in (0 until 100).zip(100 downTo 0)) {
println("i: $i, j: $j") I: 0, j: 100 ~ I: 99, j: 1
}
Copy the code
You will notice that the output of all three loops is the same. For reasons of length, we will introduce the Kotlin multivariable loop
Defining multivariable
In Kotlin’s for, the in keyword is usually used to define a loop variable, or to indicate the index or each element of the loop container. The loop container is not considered here, only the variable that defines the loop. When multiple variables need to be defined inside (), each variable is separated by a comma. After the in keyword, you set the loop
for((i,j) in...). {}Copy the code
Set loop interval
If you haven’t noticed, kotlin’s for loop defines a variable without giving it an initial value. Instead, it specifies the interval in which it needs to loop and whether it is a descending or a positive loop, so the in loop described above starts with a defined variable rather than an initial value
Now set the loop ranges for the above defined loop variables. Multiple loop ranges are set using the.zip() function
for ((i, j) in (0 until 10).zip(1 until 10)) {
println("i: $i, j: $j")}Copy the code
The above code means that the range of I is in ascending order from 0 to 10, and the range of j is in ascending order from 1 to 10
So let’s print out the result
Right? Shouldn’t I be 0 to 9? Why does it end at 8? Don’t worry, let’s look at j’s cycle interval from 1 to 10, okayUntil left closed right openWe have one fewer j cycles than I cycles, so we’re done. You might be confused, why is it over shouldn’t I output to 9, don’t worry, we’re writing the same code in Java
for (int i = 0, j = 1; i < 10 && j < 10; i++, j++) {
System.out.println("i:" + i + ", j:" + j);
}
Copy the code
The output is consistent, and the code should make sense with Java
Let’s continue to
Three variables and four variables
Sometimes there are three or four variables in the loop and you don’t know where to start. Try zip().zip() and you’ll get an error
for((i,j,k) in (0.100.).zip(0.100.).zip(0.100.)) {}// Error code
Copy the code
Kotlin: Destructuring declaration initializer of type Pair<Pair<Int, Int>, Int> must have a ‘component3()’ function
So you can’t say, three variables or four variables or more, you need to use a Pair as a loop variable, Pair is a binary tuple, you can assign multiple values to one variable at the same time, you can assign multiple values to multiple variables at the same time, there’s a binary tuple, Triple, However, I did not use three points in the learning process, it seems that the current for loop only supports binary tuples (zip() returns binary tuples). If there is anything wrong, welcome to know the details of the big man to correct, I will also modify this article at the first time
All right, let’s get started
Three variables
Very little has changed. In is still preceded by two variables, but one of them stores a tuple with values inside
On the first code
for ((i, jPair) in (1.100.).zip((0.100.).zip(0.100.)) ) {
println("i: $i.$jPair")}Copy the code
You will find that calling two zip functions, as if we haven’t introduced the functions of the zip function, will cross the bridge when it comes to the output
And you’ll notice that at the end of the output, jPair becomes an object, and at this point, jPair is a tuple object, and the output object has two values in it, and we just output something like this, what if we want to get one of those values? So write
for ((i, jPair) in (1.100.).zip((0.100.).zip(0.100.))) {
println("i: $i | jPair.firstValue: ${jPair.first} | jPair.secondValue: ${jPair.second}")}Copy the code
Output result:A binary tuple can store only two values, both of which can passObject.first and object.secondNow let’s go back to zip.
Zip () is introduced
Returns a list of pairs built from the elements of this collection and other collection with the same index. The returned list has length of the shortest collection.
Zip () returns the set with the smallest index as the index, and takes the intersection of the two sets.
If you’re confused, I am too. Let’s skip the comments and look at the parameters that the source code receives and returns
public infix fun <T, R>可迭代<T>.zip(other: 可迭代<R>): List<Pair<T, R>> {
return zip(other) { t1, t2 -> t1 to t2 }
}
Copy the code
The received parameter needs to be a type that implements the Iterable interface. Kotlin’s commonly used data storage structures actually implement this interface, and our interval expressions also support this interface.
After looking at the return value, which returns a list of tuple objects, you can look at the three-variable for loop and see if it’s self-explanatory
Four variables
So let me write the four variables, and I won’t go into the details, but it’s just a little bit different from the three variables
for ((iPair, jPair) in ((1.100.).zip(1.100.)).zip((0.100.).zip(0.100.))) {
println("iPair: $iPair | jPair: $jPair")}Copy the code
Execution Result:
To fetch the value of a tuple object, as I mentioned above, I won’t repeat it here.
summary
In general, Kotlin is quite complex when it comes to multivariable loops, but if you are familiar with the syntax, it can look very concise, but it is rarely used in daily development, just to mention that Kotlin can only do so much. If you don’t write your own examples, you’ll get a better idea of how the zip() function works and how the for loop executes the flow when it’s multivariable
Cycle control
Sometimes we need some control over the loop, and Kotlin is unique in this regard
Structural jump expression
Like most languages, Kotlin’s for loop has two structured jump expressions:
- Break: Terminates the closest loop
- Continue: Jumps out of the most recent loop
for (i in 0 until 10) {
if (i == 5) break // Output: 0 ~ 4
}
for (i in 0 until 10) {
if (i == 5) continue // Output: 0 ~ 9
}
Copy the code
Tag name
Tag naming is one of the most interesting things about Kotlin loops. We can assign a tag to a loop and then use a structural jump expression to manipulate the tag for the loop.
Name format: label name @
To break out of a specified tag, write: break@ tag name or continue@ tag name
all@ for (i in 0 until 100) {
inner@ for (j in 100 downTo 0) {
if (i == 60) break@inner
if (j == 60) continue@all
println("j: $j")
}
println("i: $i")}Copy the code
You can try it yourself, and the results will not be posted here
conclusion
Kotlin’s For loop is fairly well summarized, from simple use to multivariable, traversing common containers, and loop control. This is my first article. Some of the points may not be well described, but I believe that if you try with the code, you will soon understand what I want to express. Finally, thank you for reading!