5

In Java:

for(int j = 0; j < 6 && j < ((int)abc[j] & 0xff); j++) { // ... } 

How we can make this loop in Kotlin?

1
  • Please format your code. This makes it better readable. Commented Jul 21, 2017 at 6:36

6 Answers 6

9

I'd suggest to use a more functional approach like

(0..5).takeWhile { it < (abc[it].toInt() and 0xff) // or `as Int` if array is not numeric }.forEach { // do something with `it` } 
Sign up to request clarification or add additional context in comments.

3 Comments

This code is not equivalent. Should use takeWhile instead of filter.
@AlexFilatov Thanks, you're right. I'll update this post
Also, the whole range is processed by takeWhile before the first iteration of forEach executes. If your condition depends on the iterations side effects, this won't work.
5

If you don't mind creating a new ArrayList instance, it can be done like this:

(0..5).takeWhile { it < (abc[it] as Int and 0xff) } .forEach { // ... } 

3 Comments

Note: the whole range is processed by takeWhile before the first iteration of forEach executes. If the condition depends on the iterations side effects, this won't work.
@hotkey What do you mean by the iterations side effects? AFAIK, takeWhile doesn't loop through the whole range. Instead, it breaks the iteration when the function return false.
I mean, takeWhile will process the whole range and return the prefix before the forEach body gets even called for the first item. In the Java loop in question, on contrary, the condition gets evaluated before each iteration of the body and thus takes into account the side-effects of the body (the changes the body made to the program state). Therefore this functional solution is not equivalent to the Java loop.
5

Note: the .takeWhile { ... }.forEach { ... } approach suggested in some answers is not equivalent to the Java for loop. The range is first processed with .takeWhile { ... } and only then the prefix it returned is iterated over. The problem is that the execution of the .forEach { ... } body won't affect the condition of .takeWhile { ... }, which has already finished execution by the time the body gets called on the first item.

(see this runnable demo that shows how the behavior is different)

To fix this, you can use Sequence<T>. In constrast with eager evaluation over Iterable<T>, it won't process the whole set of items with .takeWhile { ... } and will only check them one by one when .forEach { ... } is up to process a next item. See: the difference between Iterable<T> and Sequence<T>.

To use the Sequence<T> and achieve the behavior that is equivalent to the Java loop, convert the range .toSequence():

(0..5).asSequence() .takeWhile { it < (abc[it].toInt() and 0xff) } .forEach { // Use `it` instead of `j` } 

Alternatively, just use the while loop:

var j = 0 while (j < 6 && j < (abc[j] as Int and 0xff)) { // do something j++ } 

1 Comment

Alternatively, to match Java's for loop even closer for more general cases of a non-fixed number of loops, use generateSequence(startingValue) { }
2

This is how the kotlin version will look like.

var j = 0 while (j < 6 && j < (abc[j] as Int and 0xff)) { // do something j++ } 

You can convert Java to Kotlin online here. Try Kotlin. Also if you are using IntelliJ, here is a link to help you convert from Java to Kotlin. IntelliJ Java to Kotlin.

1 Comment

j++ will not compile since j is val
0

I would move the j < ((int)abc[j] & 0xff) part into an if-test inside the loop. You could then do this:

for (j in 0..5) { if (j < (abc[j].toInt() and 0xff)) { // Do stuff here } else break } 

1 Comment

Ah, true. Will fix.
-1

This is the output of the intellij plugin for conversion:

 var j = 0 while (j < 6 && j < abc[j] as Int and 0xff) { j++ // ... } 

1 Comment

Note: in the Java for-loop, j++ is done in the end of the iteration, not as its first statement.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.