【问题标题】:How to retrieve a field value of an Object stored in a LinkedList?如何检索存储在 LinkedList 中的对象的字段值?
【发布时间】:2021-02-05 13:40:44
【问题描述】:

我是编程新手,遇到了访问问题。 目前我尝试练习 LinkedList - 通过自己创建一个然后使用它。

我在同一个目录中有 3 个类 - 自定义的“MyLinkedList”,另一个自定义的,我称之为“月”和“主”。我的想法是创建 12 个月份对象类,因为每个对象都有 3 个字段并将它们添加到 LinkedList - 我做到了。现在我有问题,当我想检索某个对象字段的某个值时。我得到了对象的地址,但不知道如何到达这个地址后面的值。

示例 - 我创建了一个包含 12 个节点的 MyLinkedList,并在每个节点中放置了一个 Month 类型的对象。稍后我想说获取名为 'season' of March 的字段(Month 类型的对象),它存储在我的 Linked List 中。

我做什么 - 访问我的 LinkedList 中名为“item”的字段,该字段包含一个 Month 类型的对象(对象的地址)。现在我想不通,我该如何进一步,到达该地址后面的对象并检索该对象的字段保留的值。

我的理解是 - 1)我在堆栈中有一个名为“myList”的引用变量,其中包含堆中“MyLinkedList”类型的对象的地址。 2) 内存中与该地址对应的位置保存了 12 个“节点”的另外 12 个地址。 3)每个节点(一块内存),保存一个对象“月”的地址。 4)内存中对应于月份地址的位置保存了(对象的)3个字段的地址。 5) 在最后一个地址(字段的)后面放置了所需的值。所以我只能达到第 3 步,但无法继续。您能建议如何进行下一步。

我把这3种方法的一些代码:

这是我的代码:

public class MyLinkedList {

    private class Node{

        Object item;
        Node next;

        Node(Object item){
            this.item = item;
            this.next = null;
        }

        Node(Object item, Node next){
            this.item = item;
            this.next = next;
        }
    }

    private Node head;
    private Node tail;
    private int count;

    public void addNode(Object element){
        Node newNode = new Node(element);
        if(head == null){
            head = newNode;
            head.next = tail;
            tail = head;
        }
        else {
            tail.next = newNode;
            tail = newNode;
        }
        count++;
    }
    
    public void printList(){
        Node currentNode = head;
        while(currentNode != null){
            if(currentNode.next != null){
                System.out.print(currentNode.item + ", ");
            }
            else {
                System.out.println(currentNode.item + ";");
            }
            currentNode = currentNode.next;
        }
    }
}
public class Month {

    private String season;
    private int length;
    public int index;

    public Month(int index){
        this.index = index;
    }

    public String getSeason(){
        return season;
    }

    public void setSeason(String season){
        this.season = season;
    }

    public int getLength(){
        return length;
    }

    public void setLength(int length){
        this.length = length;
    }
}
public class Main {
    public static void main(String[] args) {

        Month January = new Month(0);
        Month February = new Month(1);
        Month March = new Month(2);
        /*
        ....more of the same here
        */
        January.setLength(31);
        February.setLength(28);
        March.setLength(31);
        /*
        ....more of the same here
        */
        January.setSeason("Winter");
        February.setSeason("Winter");
        March.setSeason("Spring");
        /*
        ....more of the same here
        */

        MyLinkedList myList = new MyLinkedList();

        myList.addNode(January);
        myList.addNode(February);
        myList.addNode(March);
        /*
        ....more of the same here
        */

        System.out.println("Initially created list:");
        myList.printList();
        System.out.println();
        
}

【问题讨论】:

  • 你在哪里初始化myList?在 Main 类中使用它,但不要声明或初始化它。
  • 感谢您的来信。我刚刚剪掉了部分代码,但错过了……我在 Main 方法中声明并初始化 myList,就在将元素添加到列表之前。现在它被编辑了。

标签: java object linked-list reference field


【解决方案1】:

首先,如果您使用泛型MyLinkedList(如MyLinkedList<Month>),您将能够立即从这种泛型列表中获取Month 类型的对象,而无需任何转换。

在您的特定情况下,您必须将Object 类的对象显式转换回Month 类,如下所示:Month m = (Month)obj,其中obj 是您从MyLinkedList 获得的示例项目。

【讨论】:

  • 谢谢。我的想法(因为我现在正在学习并尝试做练习)是这个 MyLinkedList 实现可用于不同的场景。所以演员阵容对我有用。
  • 使其通用化将使其可用于任何类型的对象。
【解决方案2】:

由于itemNode 类中属于Object 类型,因此您需要在通过Month 类中定义的getter 方法访问任何实例字段之前将其强制转换为Month

以下代码显示了如何访问链表每个节点上Month 对象的实例字段的示例。

public void printList(){
    Node currentNode = head;

    while(currentNode != null){
        Month m = (Month) currentNode.item;
        System.out.println(m.getSeason());     // print season
        System.out.println(m.getLength());     // print length
        
        currentNode = currentNode.next;
    }
} 

注意:如果将Node类中的item的类型更改为Month,那么在访问它之前不需要将currentNode.item转换为Month实例字段。

或者,您可以覆盖返回Month 类实例的字符串表示形式的toString() 方法。这样做将允许您将 Month 类的实例传递给 System.out.println() 以打印该实例的详细信息。

public class Month {
    ...
    
    @Override
    public String toString() {
        return "Season: " + this.season + "\nLength: " + this.length;
    }
}

现在,你可以这样做:

public void printList(){
    Node currentNode = head;

    while(currentNode != null){
        Month m = (Month) currentNode.item;
        System.out.println(m);              // print season and length
        
        currentNode = currentNode.next;
    }
} 

System.out.println(m); - 此语句将打印 toString() 方法返回的任何内容,该方法在 Month 类中被覆盖。

同样,如果您将 Node 类中 item 的类型更改为 Month,则无需将 currentNode.item 转换为 Month。在这种情况下,您可以这样做:

System.out.println(currentNode.item);             
        

【讨论】:

  • 感谢您的详细解释。
【解决方案3】:

如果只是为了打印目的,我建议为Month 类创建一个toString() 函数,然后在你的printList() 方法中调用它。

Month 类的toString 方法,由 Intellij 生成:

@Override
public String toString() {
    return "Month{" + index + ", " + season + ", " + length + '}';
}

但话又说回来,您的 LinkedList 包含节点,因此您也必须为 Node 类创建 toString() 方法:

@Override
public String toString() {
    return item.toString();
}

当您完成所有这些操作后,只需修改您的 printList() 方法:

public void printList(){
    Node currentNode = head;
    while(currentNode != null){
        if(currentNode.next != null){
            // call toString function
            System.out.print(currentNode.toString() + ", ");
        } else {
            System.out.println(currentNode.toString() + ";");
        }
        currentNode = currentNode.next;
    }
}

【讨论】:

  • @Yousaf 不,它在Month 类中调用toString(),因为@Override 注释。
  • 谢谢。我会将其保留用于更通用的目的,而不仅仅是用于打印。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-15
  • 2019-05-10
  • 1970-01-01
  • 2018-05-07
  • 2020-08-09
  • 2015-04-02
  • 2011-12-22
相关资源
最近更新 更多