2016-03-02 102 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>())的实例。在任何情况下,编译器都会为您提供所需的支持,以保持列表的正确性。