我想检查List<Int?>
是否存在空值,如果不存在空值,则允许List作为List<Int>
继续,否则使用emptyList()
这是我想到的
var noNullElements: List<Int> = emptyList()
if (listWithPossibleNullElements.all { it != null }) {
noNullElements = listWithPossibleNullElements as List<Int>
}
//do something with noNullElements list
如果这是最好的,最地道的方式,我会感到震惊。
- 解决方案**
下面有许多可接受的解决方案,但我选择的是这些解决方案的组合
fun getSafeList(list: List<Int?>): List<Int> =if (null in list) emptyList() else list.requireNoNulls()
4条答案
按热度按时间kpbpu0081#
使用contains检查是否存在至少一个 null 值:
编辑:添加此扩展功能:
没有 null 元素的示例:
包含部分(或全部)null 元素的示例:
pkmbmrz72#
下面是一个一行扩展函数:
takeIf {}
-一个作用域函数,如果lambda的值为false,则返回nullnull !in it
-使用in
运算符函数确定列表是否包含null
takeIf {}
返回一个非空值,filterNotNull()
将把元素类型从可空T?
转换为非空T
注意,如果提供的
Iterable<T?>
包含null
,它将返回null
,否则返回List<T>
,以防提供的列表是空的还是包含null
。示例用法-run in Kotlin Playground:
注意:我用
requireNoNulls()
替换了filterNotNull()
,因为后者不会示例化新列表jpfvwuh43#
我认为你的问题是你想把一个泛型的
List<Int?>
类型当作List<Int>
来处理,这意味着要强制转换它。因为List<Int?>
不是List<Int>
的子类型(尽管相反的情况也是正确的,正如 Joffrey 在注解中指出的),在这种情况下你基本上必须执行一个未检查的强制转换:编译器不够聪明,无法在运行时确定这是一个安全的强制转换(你必须自己保证,例如,确保在检查通过后列表不会被修改为包含空值),所以你会得到一个 unchecked cast 警告。但是如果你真的想传入一个
List<Int?>
并把它当作一个List<Int>
,你就必须隐藏这个警告:通过使用
@Suppress("UNCHECKED_CAST")
注解出现未检查的强制转换警告的语句或声明,可以取消该警告我认为更 * 惯用 * 的方法是创建一个新的
List<Int>
,而不是尝试将原始的List<Int>
强制转换为不同的泛型类型,或者让原始的列表提供程序传递一个List<Int>?
(即如果有任何非空元素,则传递 null),这可能只是移动了问题-但这实际上取决于您在做什么。您可以轻松地创建过滤后的副本,并将其与原始副本进行比较以决定是否使用它,或者编写一个
for
循环来构建一个新列表,如果遇到null,该列表将短路,诸如此类的事情。(包括一些抛出异常的方法,如requireNoNulls()
),因此您有很多选择,并且有不同的权衡-这实际上取决于您正在做什么以及瓶颈在哪里(如果有的话)。当你使用泛型时,事情可能会变得有点笨拙,所以有些情况看起来并不像你希望的那样整洁!ctehm74n4#
尝试使用
filterNotNull
: