5

In Java:

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

How we can make this loop in Kotlin?

marstran
  • 26,413
  • 5
  • 61
  • 67

6 Answers6

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`
}
guenhter
  • 11,255
  • 3
  • 35
  • 66
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 {
            // ...
        }
BakaWaii
  • 6,732
  • 4
  • 29
  • 41
  • 2
    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 Jul 21 '17 at 11:22
  • @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. – BakaWaii Jul 21 '17 at 11:44
  • 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. – hotkey Jul 21 '17 at 11:49
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++
}
hotkey
  • 140,743
  • 39
  • 371
  • 326
  • Alternatively, to match Java's for loop even closer for more general cases of a non-fixed number of loops, use `generateSequence(startingValue) { }` – Jolt151 Feb 24 '22 at 03:22
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.

nayem
  • 7,285
  • 1
  • 33
  • 51
Alf Moh
  • 7,159
  • 5
  • 41
  • 50
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
}
marstran
  • 26,413
  • 5
  • 61
  • 67
-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++
      // ...
 }
aygavras
  • 170
  • 2
  • 11
  • Note: in the Java for-loop, `j++` is done in the end of the iteration, not as its first statement. – hotkey Jul 21 '17 at 12:13