使用 Scala 检查 null 和整数比较的最佳方法

best way to check for null and integer comparison using Scala

我在 Scala 中有 2 个链表,节点 class 定义如下:

class node(_x: Int = 0, nxt: node = null) {
    var x = _x
    var next = nxt
}

我想将两个链表(将按升序排序)合并到第三个排序列表中。 在 Scala 中执行此操作的最佳方法是什么。

我的解决方案:

object Solution {
    def mergeTwoLists(list1: node, list2: node): node = {
        (list1.x >= list2.x) match {
            case true => ListNode(list2.x, mergeTwoLists(list1, list2.next))
            case false => ListNode(list1.x, mergeTwoLists(list2, list1.next))
        }
    }
}

然而,当我 运行 这样做时,我得到以下 2 个列表的 nullPointerException [1,2,4] [1,3,4]

如果将 println((list1, list2)) 放在函数的开头,您会发现在某些时候您正在将 Node(4,null)null 进行比较。


在修复它之前,您的代码充满了代码异味和不遵循 Scala 最佳实践的东西:

  • 在 Scala 中,您真的不应该得到 NullPointerException,因为您应该永远不会有意使用 null。这就是选项的用途。
  • 定义 classes 时使用大写字母(即 Node over node)。
  • 你的 class 定义太过 Java-y 和 over-complicated。它可以简化为 case class Node(x: Int = 0, next: Node = null)(忽略 null 的不正确使用)而无需 private/public 变量 stuff.
  • 您的函数中有一个不必要的模式匹配 - 它在技术上没有任何问题,但是在 true/false 上匹配而不是使用 if 语句有点奇怪(注意:主观)。

所以 re-write 你的(仍然损坏的)功能,它看起来更像这样:

case class Node(x: Int = 0, next: Node = null)

def mergeTwoLists(list1: Node, list2: Node): Node = {
  if (list1.x >= list2.x) {
    Node(list2.x, mergeTwoLists(list1, list2.next))
  } else {
    Node(list1.x, mergeTwoLists(list2, list1.next))
  }
}

mergeTwoLists(Node(1, Node(2, Node(4))), Node(1, Node(3, Node(4))))

关于修复它:

  • 更改 class 定义以使第二个参数可选(以避免 null):
case class Node(x: Int = 0, next: Option[Node] = None)
  • 更改您的函数,使第二个参数可选以解决此问题:
def mergeTwoLists(list1: Node, list2: Option[Node]): Node = {
  ???
}
  • 您需要知道第二个列表是否存在。如果是 None,则只 return 第一个列表。否则,继续:
def mergeTwoLists(list1: Node, list2: Option[Node]): Node = {
  list2 match {
    case None => list1
    case Some(list) => ???
  }
}
  • 最后,修改您的原始 if/else 以说明节点中新的可选第二个参数:
def mergeTwoLists(list1: Node, list2: Option[Node]): Node = {
  list2 match {
    case None => list1
    case Some(list) =>
      if (list1.x >= list.x) {
        Node(list.x, Some(mergeTwoLists(list1, list.next)))
      } else {
        Node(list1.x, Some(mergeTwoLists(list, list1.next)))
      }
  }
}

现在,如果您传入输入,您将获得更合理的输出:

mergeTwoLists(
  Node(1, Some(Node(2, Some(Node(4))))),
  Some(Node(1, Some(Node(3, Some(Node(4))))))
)

产出

Node(1,Some(Node(1,Some(Node(2,Some(Node(3,Some(Node(4,Some(Node(4,None)))))))))))

注意:我不知道这是否是“最佳”方式,但它是如何使用您已经提供的功能解决您的问题。我还考虑将变量重命名为 list1list2list 有点令人困惑。

Scastie 正在工作:https://scastie.scala-lang.org/tUPoVzKpRRSJjZz62KsmhQ