簡體   English   中英

Kotlin 中 for 循環的 IndexOutOfBoundsException

[英]IndexOutOfBoundsException for for-loop in Kotlin

我在 Kotlin 中有兩個相同大小的列表, foodObjects: MutableList<ParseObject>? checked: MutableList<Boolean>? . 每次checked的元素為真時,我都需要執行一個for循環並從foodObjects獲取objectId 所以在 Java 中是這樣的:

for (int i = 0; i < foodObjects.size(); i++) {
    // here
}

但是在Kotlin,不知道為什么,出現了一些問題。 事實上,如果我這樣做:

for (i in 0..foodObjects!!.size) {
    if (checked?.get(i) == true) {
        objectsId?.add(foodObjects.get(i).objectId)
    }
}

我有IndexOutOfBoundsException 我不知道為什么,它還在foodObjects.size處繼續循環。 我也可以使用filtermap來做到這一點:

(0..foodObjects!!.size)
    .filter { checked?.get(it) == true }
    .forEach { objectsId?.add(foodObjects.get(it).objectId) }

但我遇到了同樣的錯誤。 我用它來停止錯誤並讓它工作:

for (i in  0..foodObjects!!.size) {
    if (i < foodObjects.size) {
        if (checked?.get(i) == true) {
            objectsId?.add(foodObjects.get(i).objectId)
        }
    }
}

每個人都可以告訴我為什么我需要在 Kotlin 中這樣做,而在 Java 中效果如何?

Kotlin中的范圍是包含范圍的,因此0..foodObjects!!.size始於0 ,結束於foodObjects.size ,包括兩端。 當您的循環嘗試使用自己的大小索引列表時,這會導致異常,該大小比最大有效索引大一。

要創建不包含上限的范圍(如Java循環),可以使用until

for(i in 0 until foodObjects!!.size) {
    // ...
}

如果您對正在使用的集合進行了空檢查,那么還可以稍微清理一下代碼:

if (foodObjects != null && checked != null && objectsId != null) {
    for (i in 0 until foodObjects.size) {
        if (checked.get(i) == true) {
            objectsId.add(foodObjects.get(i).objectId)
        }
    }
}
else {
    // handle the case when one of the lists is null
}

為了擺脫完全處理索引的麻煩,您可以使用列表的indices屬性(此外,我在這里使用索引運算符而不是get調用):

for (i in foodObjects.indices) {
    if (checked[i]) {
        objectsId.add(foodObjects[i].objectId)
    }
}

您還可以使用forEachIndexed

foodObjects.forEachIndexed { i, foodObject ->
    if (checked[i]) {
        objectsId.add(foodObject.objectId)
    }
}

查看Kotlin文檔中有關范圍的以下示例:

if (i in 1..10) { // equivalent of 1 <= i && i <= 10
    println(i)
}

如你看到的

1,2,3,4,5,6,7,8,9,10

將被打印。 因此,其中包括10個。

集合foodObjects的最高索引是(foodObjects.size() - 1)因為它以0開頭。

因此,要解決您的問題,只需執行以下操作:

for(i in  0..(foodObjects.size - 1)) { 
   // ...
}

更好的寫法是:

for((i, element) in foodObjects.withIndex()){
   // do something with element
   println("The index is $i")
}

這樣,您就可以一次擁有元素和索引,而不必擔心范圍。

*為簡單起見,我刪除了空檢查。

以下是確保索引有效的各種方法:

if (index in myList.indices) {
  // index is valid
}
// The rangeUntil operator (..<) is still exprimental in Kotlin 1.7.20
if (index in 0..<myList.size) {
  // index is valid
}
if (index in 0 until myList.size) {
  // index is valid
}
if (index in 0..myList.lastIndex) {
  // index is valid
}
if (index >= 0 && index <= myList.lastIndex) {
  // index is valid
}
// Note: elements of the list should be non-null
if (myList.getOrNull(index) != null) {
  // index is valid
}
// Note: elements of the list should be non-null
myList.getOrNull(index)?.let { element ->
  // index is valid; use the element
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM