gpt4 book ai didi

kotlin - 将 List 转换或转换为 List?

转载 作者:行者123 更新时间:2023-12-02 13:03:13 25 4
gpt4 key购买 nike

我正在寻找一种方便的方法来安全地转换 List<T?>List<T>? (或者,更一般地, Iterable<T?>Iterable<T>? )而不过滤任何元素。

换句话说,如果所有元素都不为空,则取列表。

在 swift 我可以这样做:

let a: [Int?] = [1, nil, 3]
let b: [Int?] = [1, 2, 3]

let aa = a as? [Int] // nil
let bb = b as? [Int] // [1, 2, 3]

在 Kotlin 中,看起来相似的代码只是执行未经检查的强制转换,不会导致 aa正在 null :
val a = listOf<Int?>(1, null, 3)
val b = listOf<Int?>(1, 2, 3)

val aa = a as? List<Int> // [1, null, 3]
val bb = b as? List<Int> // [1, 2, 3]

因此,我正在寻找这样的方法:
@Suppress("UNCHECKED_CAST")
fun <T : Any> Iterable<T?>.takeIfAllNotNull(): Iterable<T>? =
takeIf { all { el -> el != null } } as? Iterable<T>

有了它,我可以编写如下代码:
val a = listOf<Int?>(1, null, 3)
val b = listOf<Int?>(1, 2, 3)

val aa = a.takeIfAllNotNull() // null
val bb = b.takeIfAllNotNull() // [1, 2, 3]

我一定在这里遗漏了一些东西。标准库没有这样的方法吗?

最佳答案

没有内置功能,但您可以组合 filterNotNulltakeIf获得所需的行为:

val a: List<Int?> = listOf(1, null, 3)
val aa: List<Int>? = a.filterNotNull().takeIf { it.size == a.size }

--

编辑:根据@DrawnRacoon 的建议,使用 takeIf 会更快:
val aa: List<Int>? = a.takeIf { null !in a } as List<Int>

这不会创建中间列表,并且在找到空值时会短路。它确实需要不安全的强制转换来强制编译器更改类型。

在扩展函数中提取它看起来像这样:
@Suppress("UNCHECKED_CAST")
fun <T> Iterable<T?>.takeIfAllNotNull(): Iterable<T>? {
return takeIf { null !in this } as? Iterable<T>
}

看来我们已经回到了你原来的提议。所以也许答案应该是:

没有 ,你没有错过任何东西。
标准库中没有针对这种确切行为的方法。

要触及问题中发生的事情:
它与泛型侵 eclipse 有关。在运行时没有泛型,所以类型转换只是 ListList它总是成功,它返回原始对象。
编译器将正确警告您有关不安全的强制转换。忽略此警告可能会导致运行时的类型不正确:
val a = listOf(1, null, 3)     
val aa = a as? List<Int> // unsafe cast List<Int?> to List<Int>
// aa is now List<Int> but contains a null

您正在转换 List<Int?>List<Int>但运行时无法区分这些类型。
为了安全地转换它,我们实际上必须在某个地方检查列表的内容。最好明确地这样做,以便清楚发生了什么,因此在我们的示例中调用了额外的函数。

关于kotlin - 将 List<T?> 转换或转换为 List<T>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60324349/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com