更改列表元素的nullability而无需复制列表

huangapple go评论55阅读模式
英文:

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 &lt;T: Any&gt; List&lt;T?&gt;.asNonNullable(): List&lt;T&gt; {
    if(any { it == null }) throw IllegalArgumentException(&quot;unexpected null element&quot;)
    @Suppress(&quot;UNCHECKED_CAST&quot;)
    return this as List&lt;T&gt;
}

答案2

得分: 0

To avoid the unchecked cast warning you can use filterIsInstance

baz(a.filterIsInstance&lt;Int&gt;())

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&lt;Int&gt;())

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.

huangapple
  • 本文由 发表于 2023年5月17日 23:37:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76273841.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定