首页 > 解决方案 > 这些在 Kotlin 中创建列表的方式有什么区别?我的结果 1 有效,但结果 2 无效

问题描述

val list1 = listOf(1,2,3,4,5,6,7,8,9)
val list2 = listOf(1..9)

/* 我的结果 1 是有效的,但结果 2 给出了错误 */

val result1= list1.filter{i -> i>2} 

val result2 = list2.filter{i -> i>2}

标签: kotlin

解决方案


listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)

是一个由九个数字组成的列表——具体来说,Ints。

然而,1..9是一个范围对象——特别是一个IntRange. 所以:

listOf(1..9)

是一个包含单个对象的列表。

list1.filter{ i -> i > 2 }

是有效的,因为filter()将它的 lambda 应用到Int列表中的每个 - 并且>运算符定义在两个Ints 之间。然而:

list2.filter{ i -> i > 2 }

无效,因为 lambda 应用于IntRange,并且您无法将 anIntRange与 an进行比较Int


你的 IDE 和编译器应该给你一些关于这个的线索。首先,如果您将鼠标悬停在上面list1list2您将看到编译器为它们推断的类型:List<Int>List<IntRange>,分别。

IDE 不仅下划线{ i -> i > 2 },它还显示>红色。将鼠标悬停在上面会显示错误“未解决的参考”。由于接收器类型不匹配,以下候选均不适用……' 这有点神秘,但您应该了解它,因为它很常见且非常有用。它告诉您您正在尝试调用未为您拥有的类型定义的函数/方法/运算符。在这种情况下,>(相当于compareTo())是为两个Ints、两个Longs、两个Strings 等定义的,但不是为 anIntRange和 an定义的Int

所以编译器不知道它应该有什么返回类型,并暂时假设Unit——但filter()需要一个返回 a 的 lambda Boolean,这就是为什么整个 lambda 带有“类型不匹配”错误下划线的原因。


正如 Tenfour04 所说,如果需要(使用方法) ,您可以将范围转换为列表。toList()但在实践中,这并不经常需要,因为通常有更好的方法。(范围比大多数列表占用的内存少得多,因此迭代速度更快;并且它实现Iterable了,所以无论如何你已经可以用它做大多数列表类型的事情了。)


推荐阅读