天天看點

scala 實作連結清單

在學習資料結構時學到了連結清單,因為日常工作,寫java寫多了,想換個語言玩下,就試着想用scala實作一個連結清單。哪到知道碰到很多問題,

這裡記錄下使用scala時,所遇到的那些坑。

java連結清單

首先,我們先使用java來實作一個連結清單最簡單的連結清單

public static class Node<T> {

    /**
     * 這裡為了友善,就不用get和set方法那一套了
     */
    public Node next;

    public T data;

}
           
public static void main(String[] args) {
    Node<Integer> headNode = new Node<>();
    headNode.data = 1;

    Node<Integer> secondNode = new Node<>();
    secondNode.data = 2;
    headNode.next = secondNode;

    Node<Integer> thirdNode = new Node<>();
    thirdNode.data = 3;
    secondNode.next = thirdNode;

    Node<Integer> fourthNode = new Node<>();
    fourthNode.data = 4;
    thirdNode.next = fourthNode;

    Node<Integer> fifthNode = new Node<>();
    fifthNode.data = 5;
    fourthNode.next = fifthNode;

    //周遊node
    Node<Integer> currentNode = headNode;
    while (currentNode != null) {
        System.out.println(currentNode.data);
        currentNode = currentNode.next;
    }
}
           

代碼很簡單,就不解釋了,我們使用java實作了如下的數組。

scala 實作連結清單

同樣的代碼,我們使用scala實作一遍。

scala連結清單

case class Node[E](var next: Node[E], var data: E) {
}

def main(args: Array[String]): Unit = {
    val headNode = Node(null, 1)

    val secondNode = Node(null, 2)
    headNode.next = secondNode

    val thirdNode = Node(null, 3)
    secondNode.next = thirdNode

    val fourthNode = Node(null, 4)
    thirdNode.next = fourthNode

    val fifthNode = Node(null, 5)
    fourthNode.next = fifthNode

    var currentNode = headNode
    while (currentNode != null) {
      println(currentNode.data)
      currentNode = currentNode.next
    }
}
           

使用scala來實作連結清單也非常簡單,除了預發以外基本上和java一模一樣。

頭部節點

好像從上面看,也沒啥問題啊。考慮這樣的情況,我們在實作一個連結清單時,經常會有一個設定一個不表示任何意義的頭結點,以便于統一連結清單的操作(add和remove操作)

scala 實作連結清單

先來看看使用java如何建立這樣一個“空節點”

public static class Node<T> {

    /**
     * 這裡為了友善,就不用get和set方法那一套了
     */
    public Node next;

    public T data;

}

public static class List<T>{

    private Node<T> headNode = new Node<>();
}

public static void main(String[] args) {
   
    List<Integer> list = new List<>();

}
           

沒啥問題

同樣的代碼,看看scala

scala 實作連結清單

報了個錯,Type mismatch, expected:E actual:Null ,scala的泛型不止是用于引用類型。

scala 實作連結清單

看這個圖可以知道,

null僅僅是AnyRef的子類

,對于AnyVal這樣的類型,比如Int,無法使用null指派。

解決方法一:限制泛型的下界

即,限制泛型必須是Null的父類型

case class Node[E](var next: Node[E], var data: E) {
}

class List[E >: Null] {
var headNode = new Node[E](null, null)
}

def main(args: Array[String]): Unit = {
    val l = new List[Integer] //問題,這裡隻能用Integer,無法使用Int了
}
           

這種方式,解決了無法使用null指派的問題。但是使用這種方式,必須使用

new List[Integer]

無法使用基本類型比如

new List[Int]

解決方法二:todo