2016-03-02 34 views
2

所以我有這個鏈表類:重新使用鏈接的另一種類型的列表(泛型類型)

public class LinkedList { 
    private LLNode rootNode; 

    public Node FindItemByData(String data) { 
     if(rootNode == null) 
      return null; 
     else 
      return rootNode.findItemByData(data); 
    } 

而這個節點類:

public class LLNode { 


    LLNode tail; //tail node 
    Node data; //some data 


    public LLNode(LLNode tail, Node data) 
    { 
     this.tail = tail; 
     this.data = data; 
    } 

    public Node findItemByData(String data) { 
     if(this.data.name.equals(data)) 
      return this.data; 
     else 
      return this.tail.findItemByData(data); 
    } 

我想重新使用鏈接列表用於在LLNode的每個Node data內的圖形中存儲邊緣。我使用Generic Types取代了類型,但是這破壞了findItemByData函數的功能,因爲它依賴於顯式聲明爲Node的數據。

有什麼辦法可以重用這個類的多種類型?或者我不應該在泛型類中提到data.name

執行方面:

public class Graph { 

    //USE LINKED LIST 
    LinkedList Nodes; 
    //Node[] Nodes; 
    int noOfNodes; 

    public Graph() { 
     noOfNodes = 0; 
     //Nodes = new Node[25]; 
     Nodes = new LinkedList(); 
    } 

    public void AddNode(String name, int x, int y) { 
     //Nodes[noOfNodes++] = new Node(name,x,y); 
     Nodes.AddItem(new Node(name,x,y)); 
    } 

..

public class Node { 
    String name; //Node's name 
    int x,y;  //Node's coords 
    LinkedList Adjacencies; 
    int noOfAdj = 0; 
    int size = 0; 


    public Node(String name, int x, int y) { //Constructor 
     this.name = name; 
     this.x = x; 
     this.y = y; 
     Adjacencies = new LinkedList(); 
    } 

    public void addAdjacency(String dest, double distance) { 
     Adjacencies.AddItem(new Edge(this.name, dest, distance)); //I want to do this 
    } 
} 

編輯:嘗試在使用泛型:

public class LinkedList<T> { 
    private LLNode rootNode; 

    public T FindItemByData(String data) { 
     if(rootNode == null) 
      return null; 
     else 
      return rootNode.findItemByData(data); 
    } 
} 

public class LLNode<T> { 


    LLNode tail; //tail node 
    T data; //some data 


    public LLNode(LLNode tail, T data) 
    { 
     this.tail = tail; 
     this.data = data; 
    } 

    public T findItemByData(String data) { 
     if(this.data.name.equals(data)) 
      return (T) this.data; 
     else 
      return (T) this.tail.findItemByData(data); 
    } 
} 

public class Graph { 

    LinkedList<Node> Nodes; 
    int noOfNodes; 

    public Graph() { 
     noOfNodes = 0; 
     Nodes = new LinkedList(); 
    } 

    public void AddNode(String name, int x, int y) { 
     Nodes.AddItem(new Node(name,x,y)); 
    } 
} 

public class Node { 
    String name; //Node's name 
    int x,y;  //Node's coords 
    LinkedList<Edge> Adjacencies; 
    int noOfAdj = 0; 
    int size = 0; 


    public Node(String name, int x, int y) { //Constructor 
     this.name = name; 
     this.x = x; 
     this.y = y; 
     Adjacencies = new LinkedList(); 
    } 

    public void addAdjacency(String dest, double distance) { 
     Adjacencies.AddItem(new Edge(this.name, dest, distance)); //I want to do this 
    } 
} 
+0

爲了闡明,節點鏈表要存儲Node類型的對象,其中作爲鄰接鏈表需要是Edge類型。 – bene96

+0

嘿埃裏克,顯示的代碼是在我嘗試泛型之前。我嘗試過'公共類LLNode {..}'並將數據聲明爲'T data',但這不起作用,因爲LLNode的方法依賴於節點類型('findItemByData') – bene96

回答

1

基本上你是說,節點和邊緣應遵守相同的合同。要做到這一點,你應該讓他們實現一個接口,該接口包含合同中所有的方法。

在這種情況下,這可能只會是getData()。然後使用這個接口爲你的方法,可以採取任何邊緣或節點。

另一種方法是使Edge成爲Node的擴展。 public class Edge extends Node。然後,無論需要哪個節點,都可以使用它。

+0

它工作正常!爲了澄清其他人,我擴展了Edge類並在Node類中創建了一個空構造函數。 – bene96

1

我認爲你對泛型的嘗試其實很接近。它的優點是使編譯器能夠確定某個特定的LinkedList是否擁有NodesEdges。所以我建議你保留LinkedList的通用參數,但是讓它有些不同。 T應該是保存在LLNode中的那種數據。訣竅是你的數據有一個String name,所以你需要一些東西來擴展,以獲得name

interface Named { 
    String getName(); 
} 

public class LinkedList<T extends Named> { 
    private LLNode<T> rootNode; 
    // etc. 
} 

public class LLNode<T extends Named> { 
    LLNode<T> tail; //tail node 
    T data; //some data 

    public LLNode(LLNode<T> tail, T data) { 
    this.tail = tail; 
    this.data = data; 
    } 

    public T findItemByData(String data) { 
    if(this.data.getName().equals(data)) 
     return this.data; 
    else 
     return this.tail.findItemByData(data); 
    } 
    // etc. 
} 

現在你可以實例化一個LinkedList持有剛Nodes,另一個剛成立Edges,假設兩NodeEdge實施Named

我已經提到,但要再次強調:這是優於只使用的Node和內LinkedListEdge的超類型的方法。在這種情況下,您可以將NodeEdge實例放在同一個LinkedList中,編譯器將無法警告您。通用方法使您能夠創建LinkedList限制爲NodeEdge或不受限制(new LinkedList<Named>())的實例。在任何情況下,編譯器都會爲您提供所需的支持,以保持列表的正確性。