英文:
Change nullability of list elements without copying list
问题
I understand your request. Here's the translated code portion:
我在调用一个无法更改的第三方函数,该函数返回一个可为空元素的列表(`List<Int?>`),但我确切知道所有元素都是非空的。然后,我想将此列表传递给另一个需要非空元素列表(`List<Int>`)的第三方函数。如果像下面的代码中所做的那样进行强制转换,会出现警告。如果使用 `filterNotNull`,它会不必要地复制列表。如何避免复制列表,同时又不触发未检查的强制转换警告?
fun foo() {
val a = bar(includeNullElements = false)
baz(a.map { it!! }) // 不希望复制大型列表
baz(a.filterNotNull()) // 不希望复制大型列表
baz(a as List<Int>) // 会产生未经检查的强制转换警告
}
/**
* 这个函数来自一个我无法更改的库。
* 返回一个已知为非空的非常大的元素列表,
* 但不幸的是它们的类型是可空的。
*/
fun bar(includeNullElements: Boolean): List<Int?> = TODO()
/**
* 这个函数来自一个我无法更改的库。
* 接受一个非空元素列表。
*/
fun baz(a: List<Int>) {
println(a)
}
Is there anything else you would like to translate or clarify?
英文:
I'm calling a third-party function (which I can't change) which returns a list of nullable elements (List<Int?>
), but I know for certain that all elements are non-null. I then want to pass this list to another third-party function, which takes a list of non-null elements (List<Int>
). If I cast it, as I do in the code below, I get a warning. If I use filterNotNull
it copies the list unnecessarily. How can I avoid copying the list and also not triggering an unchecked cast warning?
fun foo() {
val a = bar(includeNullElements = false)
baz(a.map { it!! }) // Undesirable to copy large list
baz(a.filterNotNull()) // Undesirable to copy large list
baz(a as List<Int>) // Gives unchecked cast warning
}
/**
* This function comes from a library that I can't change.
* Returns a very large list of elements known to be non-null,
* but unfortunately are typed as nullable.
*/
fun bar(includeNullElements: Boolean): List<Int?> = TODO()
/**
* This function comes from a library that I can't change.
* Takes a list of non-null elements.
*/
fun baz(a: List<Int>) {
println(a)
}
答案1
得分: 2
你可以做的是,如果你绝对不想复制列表,你可以将列表转换为非空列表,抑制未检查转换的警告,但你不会以不安全的方式进行操作,因为在进行转换之前你会检查列表:
fun <T: Any> List<T?>.asNonNullable(): List<T> {
if(any { it == null }) throw IllegalArgumentException("unexpected null element")
@Suppress("UNCHECKED_CAST")
return this as List<T>
}
英文:
What you can do if you absolutely don't want to copy the list, is that you cast the list to a non-nullable list, you suppress the warning for an unchecked cast, but you don't do that in an unsafe way, because you check the list before casting:
fun <T: Any> List<T?>.asNonNullable(): List<T> {
if(any { it == null }) throw IllegalArgumentException("unexpected null element")
@Suppress("UNCHECKED_CAST")
return this as List<T>
}
答案2
得分: 0
To avoid the unchecked cast warning you can use filterIsInstance
baz(a.filterIsInstance<Int>())
Also you can use toList()
that performs a shallow copy of the list, which is more efficient than using map
or filterNotNull
in this scenario.
See this article of shallow vs deep copy for more information about copy.
英文:
To avoid the unchecked cast warning you can use filterIsInstance
baz(a.filterIsInstance<Int>())
Also you can use toList()
that performs a shallow copy of the list, which is more efficient than using map
or filterNotNull
in this scenario.
See this article of shallow vs deep copy for more information about copy.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论