【问题标题】:Kotlin, remove duplicates from Linkedlist : smart cast is impossibleKotlin,从 Linkedlist 中删除重复项:智能演员是不可能的
【发布时间】:2021-05-23 23:11:01
【问题描述】:

我在 kotlin 中实现了一个 LinkedList,并编写了一个方法来从中删除重复项:

class Node (value:Int) {
    var value = value
    var next:Node? = null

fun addNodeToTail(value:Int){
    var node = this
    while (node.next != null) {
        node = node.next
    }
    val newNode= Node(value)
    node.next= newNode

}
fun removeDuplicates (){

    val set = HashSet<Int>()
    var node = this
    set.add(node.value)
    while(node.next != null){
        if (set.contains(node.next?.value)){
            node.next= node.next?.next
        }else{
            set.add(node.next.value)
            node= node.next
        }
    }
}
}

在最后两行:

 set.add(node.next.value)
 node= node.next

(在 addNodeToTail 方法中),编译器说智能转换是不可能的,因为表达式很复杂。我必须添加非空断言调用 (!!)。

我想了解为什么不接受此解决方案,尽管 while 表达式检查 node.next 不为空。而且我想知道是否有比使用非空断言调用(!!)更好的解决方案。

感谢您的帮助

【问题讨论】:

  • 这就是 Kotlin 空安全的工作原理。检查可变的node.next != null 并不意味着它以后不会为空,因为另一个线程可能访问该节点并修改next 属性。您需要创建一个包含 next.value 的字段并引用它。

标签: kotlin linked-list


【解决方案1】:

Pawel 在评论中技术性地回答了。

基本上,智能演员表并不总是可行的。特别是,如果您定义了一个可空类型的可变var,在技术上可以由多个线程访问,则编译器无法保证该值在空检查和使用之间保持不变。这就是为什么您会收到此错误“无法进行智能转换”。

处理该问题的常用方法是将值存储在本地val 变量中,以保证该值不会改变,并允许编译器对其进行智能转换。

但在您的情况下,这并不理想,因为 while 每次都必须检查实际节点的值。因此,您必须在某些时候断言该值不为空,无论是使用 !! 还是使用 elvis (?:) 和 error()throw

我个人会选择:

    while (node.next != null) {
        val nextNode = node.next ?: throw ConcurrentModificationException()
        if (set.contains(nextNode.value)) {
            node.next = nextNode.next
        } else {
            set.add(nextNode.value)
            node = nextNode
        }
    }

【讨论】:

  • 嗯。但是您甚至不需要多个线程;值可能会因方法调用而改变。 (而且编译器无法合理地检查这一点;它可能在任意复杂的调用序列的末尾,可能通过库中的代码可以在运行时替换......)  将值存储在局部变量中(或在诸如let()之类的作用域函数的接收器中是一个很好的解决方法。
  • @gidds true,线程只是一个例子。但是有些情况下没有方法调用,编译器很容易识别,但由于线程,它仍然不能保证任何事情。这种不可能的智能案例的问题通常出现在当前线程中什么都不会发生的情况下,因此人们大部分时间都会因此而感到困惑,因此示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
相关资源
最近更新 更多