List 在Kotlin中,如何在迭代时修改列表的内容
我有一份清单:List 在Kotlin中,如何在迭代时修改列表的内容,list,iterator,kotlin,mutable,List,Iterator,Kotlin,Mutable,我有一份清单: val-someList=listOf(1,20,10,55,30,22,11,0,99) 我想在修改一些值的同时迭代它。我知道我可以用map来做,但这就是列表的副本 val copyOfList=someList.map{如果(它首先,并非所有列表的复制都是坏的。有时,复制可以利用CPU缓存,速度非常快,这取决于列表、大小和其他因素 第二,要“就地”修改列表,您需要使用一种可变的列表类型。在示例中,您使用listOf,它返回list接口,该接口是只读的。您需要直接引用可变列表
val-someList=listOf(1,20,10,55,30,22,11,0,99)
我想在修改一些值的同时迭代它。我知道我可以用map
来做,但这就是列表的副本
val copyOfList=someList.map{如果(它首先,并非所有列表的复制都是坏的。有时,复制可以利用CPU缓存,速度非常快,这取决于列表、大小和其他因素
第二,要“就地”修改列表,您需要使用一种可变的列表类型。在示例中,您使用listOf
,它返回list
接口,该接口是只读的。您需要直接引用可变列表的类(即ArrayList
),或者使用助手函数arrayListOf
或linkedListOf
创建MutableList
引用是习惯用法。一旦创建了该引用,您就可以使用带有变异方法set()
的listIterator()
迭代列表
示例调用此扩展函数的任何变体:
val someList = arrayListOf(1, 20, 10, 55, 30, 22, 11, 0, 99)
someList.mapInPlace { if (it <= 20) it + 20 else it }
对于每个基元数组,使用以下变量:
inline fun BooleanArray.mapInPlace(mutator: (Boolean)->Boolean) {
this.forEachIndexed { idx, value ->
mutator(value).let { newValue ->
if (newValue !== value) this[idx] = mutator(value)
}
}
}
关于仅使用引用等式的优化
上面的扩展函数通过在没有更改为其他实例时不设置值进行了一些优化,检查使用==
或!=
是否正确。不值得检查equals()
或hashCode()
因为调用这些函数会产生未知的代价,而引用等式实际上会捕获任何更改值的意图
扩展函数的单元测试
以下是单元测试用例,展示了函数的工作情况,以及与stdlib函数map()
的一个小比较,该函数可以制作一个副本:
class MapInPlaceTests {
@Test fun testMutationIterationOfList() {
val unhappy = setOf("Sad", "Angry")
val startingList = listOf("Happy", "Sad", "Angry", "Love")
val expectedResults = listOf("Happy", "Love", "Love", "Love")
// modify existing list with custom extension function
val mutableList = startingList.toArrayList()
mutableList.mapInPlace { if (it in unhappy) "Love" else it }
assertEquals(expectedResults, mutableList)
}
@Test fun testMutationIterationOfArrays() {
val otherArray = arrayOf(true, false, false, false, true)
otherArray.mapInPlace { true }
assertEquals(arrayOf(true, true, true, true, true).toList(), otherArray.toList())
}
@Test fun testMutationIterationOfPrimitiveArrays() {
val primArray = booleanArrayOf(true, false, false, false, true)
primArray.mapInPlace { true }
assertEquals(booleanArrayOf(true, true, true, true, true).toList(), primArray.toList())
}
@Test fun testMutationIterationOfListWithPrimitives() {
val otherList = arrayListOf(true, false, false, false, true)
otherList.mapInPlace { true }
assertEquals(listOf(true, true, true, true, true), otherList)
}
}
以下是我提出的,与Jayson的方法类似:
inline fun <T> MutableList<T>.mutate(transform: (T) -> T): MutableList<T> {
return mutateIndexed { _, t -> transform(t) }
}
inline fun <T> MutableList<T>.mutateIndexed(transform: (Int, T) -> T): MutableList<T> {
val iterator = listIterator()
var i = 0
while (iterator.hasNext()) {
iterator.set(transform(i++, iterator.next()))
}
return this
}
inline fun MutableList.mutate(transform:(T)->T):MutableList{
返回mutateIndexed{uUt,t->transform(t)}
}
内联可变列表。可变索引(转换:(Int,T)->T):可变列表{
val iterator=listIterator()
变量i=0
while(iterator.hasNext()){
iterator.set(transform(i++,iterator.next()))
}
还这个
}
< /代码> 不必写任何新的扩展方法——是的,功能范式是令人敬畏的,但它们通常意味着不可更改性。如果你在变异,你可以考虑让旧学校隐含的:
val someList = mutableListOf(1, 20, 10, 55, 30, 22, 11, 0, 99)
for(i in someList.indices) {
val value = someList[i]
someList[i] = if (value <= 20) value + 20 else value
}
val-someList=mutableListOf(1,20,10,55,30,22,11,0,99)
对于(someList.index中的i){
val value=someList[i]
someList[i]=if(value)您不应该使用MutableListIterator
?我在迭代器中找不到set
。对于基本数组,您应该使用结构等式!=
代替引用等式!=
@AmrElAdawy,在我使用listIterator()的示例中
从可变结构返回,该结构因此返回一个可变列表迭代器
,因此上述代码可以工作。如果您键入迭代器或使用不可变列表获取迭代器,那么当然,您将使用列表迭代器
。上面的代码推断出正确的类型。@sosite引用等式y是有意的,它询问的是变体是否返回了一个新对象,而不是它是否修改了内容或返回了一个等价的对象。这只是一个快速的性能检查,并且这些列表是否可以观察到以避免触发事件。对内容进行完全平等性检查会很慢,而且这并不是有意的。@JaysonMinard,但不推荐使用基元类型参数的标识相等
class MapInPlaceTests {
@Test fun testMutationIterationOfList() {
val unhappy = setOf("Sad", "Angry")
val startingList = listOf("Happy", "Sad", "Angry", "Love")
val expectedResults = listOf("Happy", "Love", "Love", "Love")
// modify existing list with custom extension function
val mutableList = startingList.toArrayList()
mutableList.mapInPlace { if (it in unhappy) "Love" else it }
assertEquals(expectedResults, mutableList)
}
@Test fun testMutationIterationOfArrays() {
val otherArray = arrayOf(true, false, false, false, true)
otherArray.mapInPlace { true }
assertEquals(arrayOf(true, true, true, true, true).toList(), otherArray.toList())
}
@Test fun testMutationIterationOfPrimitiveArrays() {
val primArray = booleanArrayOf(true, false, false, false, true)
primArray.mapInPlace { true }
assertEquals(booleanArrayOf(true, true, true, true, true).toList(), primArray.toList())
}
@Test fun testMutationIterationOfListWithPrimitives() {
val otherList = arrayListOf(true, false, false, false, true)
otherList.mapInPlace { true }
assertEquals(listOf(true, true, true, true, true), otherList)
}
}
inline fun <T> MutableList<T>.mutate(transform: (T) -> T): MutableList<T> {
return mutateIndexed { _, t -> transform(t) }
}
inline fun <T> MutableList<T>.mutateIndexed(transform: (Int, T) -> T): MutableList<T> {
val iterator = listIterator()
var i = 0
while (iterator.hasNext()) {
iterator.set(transform(i++, iterator.next()))
}
return this
}
val someList = mutableListOf(1, 20, 10, 55, 30, 22, 11, 0, 99)
for(i in someList.indices) {
val value = someList[i]
someList[i] = if (value <= 20) value + 20 else value
}