【问题标题】:How does iterator work with constructor迭代器如何与构造函数一起工作
【发布时间】:2014-04-14 08:37:44
【问题描述】:

您好,我是 Java 新手,刚刚在作业中遇到以下问题。我需要编写一个类,在调用 void 方法时将新对象添加到列表中。作为提示,给出了迭代器方法的结构,所以我的代码的核心结构现在如下所示:

public class objectList implements Iterable<Obj> {

  private ArrayList<Obj> objectList;
  attribute_a A;
  attribute_b B;
  attribute_c C;


  public objectList(attribute_a A, attribute_b B, attribute_c C){
      objectList = new ArrayList<Obj>;
      this.A = A;
      this.B = B;
      this.C = C;
  }

  public void extendList(attribute_a A, attribute_b B, attribute_c C){
      objectList.add(new Obj(A,B,C));
  }

  public Iterator<Obj> iterator(){
      return objectList.iterator();
  }

  @Override
  public String toString(){
      newstr = "";
      for(i = 0;i<objectList.size();i++)
      {
        //Assuming Obj has the method toString()
        //It prints out all details of each object, then join into one string
        newstr += objectList.get(i).toString();
      }
      return newstr;
  }
}

我被告知只使用 java.util.iterator,而不是自定义迭代器 - 所以它让我免于定义 HasNext()、next()、remove() 等。

编辑:我的目标是能够打印存储在 objectList 中的对象,在 extendList() 被调用几次之后,即列表中存储了许多项目。现在我只能打印其中的最新项目(列表中只有一项)。

如何使“光标”自动指向下一项 -> 获取属性 -> 对属性执行任务 -> 下一项等,直到列表完成?

【问题讨论】:

  • 你是说你只能打印最后一个对象而不是所有添加的对象吗?这是你的问题吗?
  • 你的 toString 输出是什么?
  • 请给出您的问题陈述的目标或定义(您想要实现什么?)

标签: java object iterator


【解决方案1】:

让我们看看这里发生了什么......

所以,你有一个类,它有一个名为objectList 的字段。当您创建 new objectList 实例时,将调用构造函数并将字段初始化为空列表。到现在为止还挺好。 (但是,为什么你有名为ABC 的字段?它们似乎根本没有被使用,所以要求某人向你的构造函数传递三个有效的参数似乎令人困惑忽略。)

然后,每当调用extendList 时,都会将新的Obj 添加到实例列表中。这看起来是对的。这意味着在任何给定点,我们可以说objectList 的大小等于在该对象上调用extendList 的次数。

同样,调用iterator 只会返回此列表的标准Java 迭代器。所以迭代器应该访问该列表中的每个Obj,这将是等于extendList 在同一个objectList 对象上被调用的次数。

那么 - 为什么它不起作用

从您发布的代码中不清楚。你的类本身看起来不错,所以结论是你一定是把它叫错了。我的 猜测 是您实际上是在构造该类的多个实例 - 每次调用构造函数时,您都会创建一个具有不同字段的新实例。例如,这不会达到您的预期:

new objectList().extendList("A1", "B1", "C1");
new objectList().extendList("A2", "B2", "C2");
new objectList().extendList("A3", "B3", "C3");
return new objectList().iterator();

因为每次都会创建一个新实例,从而有效地抛弃之前的状态。您想将其重写为:

objectList ol = new objectList();
ol.extendList("A1", "B1", "C1");
ol.extendList("A2", "B2", "C2");
ol.extendList("A3", "B3", "C3");
return ol.iterator();

如果这不能解决问题,请查看您是如何使用该类的,计算您在从中获取迭代器的同一实例上调用 extendList 的次数。如果有疑问 - 让 Java 为您计算 - 添加 System.out.println("in extendList") 调用(可能还有一些在构造函数中)以查看何时调用什么。事实上,如果担心正在使用该类的不同实例,您可以使用 System.identityHashcode() 获取特定实例的唯一标识符,例如:

 public void extendList(attribute_a A, attribute_b B, attribute_c C){
    System.out.println("Extending list for " + System.identityHashcode() + " with " + A + ", " + B + ", " + C);
    objectList.add(new Obj(A,B,C));
 }

如果做不到这一点,可能值得熟悉如何使用调试器,并逐行单步执行您的程序。这将让您看到程序在每一步的状态,并希望它能让您清楚事情开始偏离您的期望的地方。


(我还鼓励您使用标准 Java 命名约定,因为目前没有它们,您的代码难以阅读。类名应该以大写字母开头(并且是大写字母)。变量和字段名应该以大写字母开头使用小写字母(并且使用 lowerCamelCase)。目前,您的类名看起来像一个变量,而您的字段看起来像通用参数。new objectList() 看起来不对!)

【讨论】:

  • 感谢详细的回复!这些方法由给定的测试文件调用,其中包含: ol.extendList("A","B","C") 两次,并尝试将 toString() 的结果与预期的字符串匹配。我现在将阅读更多关于标准约定和构造函数的内容。干杯!
【解决方案2】:

尝试在构造函数之外初始化这个objectList = new ArrayList&lt;Obj&gt;;

private ArrayList<Obj> objectList=new ArrayList<Obj>();

【讨论】:

  • 除了不是很清楚OP有什么问题之外,在声明点初始化列表字段或作为构造函数中的第一条语句在技术上没有真正的区别。不过,我同意它更好。但是这个答案绝不会帮助 OP 解决他的(仍有待更好解释的)问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-08
  • 1970-01-01
相关资源
最近更新 更多