【问题标题】:Cant modify ArrayList elements无法修改 ArrayList 元素
【发布时间】:2012-05-06 21:06:15
【问题描述】:

我正在创建一个由多个作者撰写的文章的数据库,所以我有两个类:作者和文章。 Article 的构造函数是

        Article(String title, String venue, Author[] authors, long year).

一个 Author 对象包含一个带有作者姓名的字符串和一个他写过的文章的 ArrayList。

所以,我有一个文章数组,我正在尝试创建一个作者数组列表并添加他们写的所有文章。

这是我的代码:

for(int i=0; i<allarticles.length; i++) {
            Author[] tempauthors = allarticles[i].getAuthors();
            for (int j=0; j<tempauthors.length; j++) {
                Author tempauthor = tempauthors[j];
                if (authors.contains(tempauthor)) {
                    Author oldAuthor = authors.get(authors.indexOf(tempauthor));
                    if (!oldAuthor.hasArticle(allarticles[i]))
                        oldAuthor.addArticle(allarticles[i]);
                } else {
                    if (!tempauthor.hasArticle(allarticles[i]))
                        tempauthor.addArticle(allarticles[i]);
                    authors.add(tempauthor);
                }
            }
        }

这里是 hasArticle 方法: public boolean hasArticle(Article a) { 返回articles.contains(a); }

我按照建议修改了 equals 方法,但现在的问题是我得到的作者拥有适量的文章,但第一个是重复的。我做错了什么?我也应该覆盖 Article.equals() 方法吗?

【问题讨论】:

  • 重读关于对象引用、身份和equals()的章节。

标签: java arraylist


【解决方案1】:

除非 Author 类有自己的机制为名称相同的 Author 对象的每个实例返回相同的 Author 对象,否则代码可以正常工作。

contains() 方法不“知道”您指的是作者的名字,它只知道您询问了特定的 Author 对象是否在 ArrayList 中。

contains() 方法使用其 equals(Object a) 方法比较整个对象。两个不同的对象相等,当且仅当 equals() 方法说它们相等。对于没有显式 equals() 方法的类(继承自 Object 或您的类扩展的另一个类除外),将使用地址(指针 ...)。

因此,您必须定义“equals()”的含义。在您的情况下,如果作者的姓名相同,则两个对象是相同的。在您的情况下,这意味着 equals() 是这种方法--

public boolean equals(Object a) {
  if (! (a instanceof Author))
    return false;

  return this.getname().equals(((Author) a).getname());
}

您的代码中似乎还有一些时髦的逻辑。您想将新文章添加到作者拥有的现有文章中。因此,您需要找到该作者的现有条目(ArrayList 中的 indexOf() 方法),获取该条目(get() 方法 ...),然后将文章添加到 ArrayList 中的 Author 对象。

要做到这一点,你需要这样做

Author oldAuthor = authors.get(authors.indexOf(tempauthor));
oldAuthor.addArticle(allarticles[i]);

而不是您拥有的 remove / addArticle / remove 代码。

您还需要确保没有将文章添加到作者已添加的文章列表中。

【讨论】:

  • 您是否更改为停止删除现有作者及其文章,而是使用 indexOf(tempauthor) 查找现有条目,然后说现有条目已添加文章?抱歉,我没有给出完整的答案,但@SLaks 一直在引导你进入“修复 equals 方法”的兔子洞。
  • @tonydanza:那是因为作者的文章列表中已经有了这篇文章。抱歉 - 您需要确保您要添加的文章不在列表中,它已经在列表中(我现在理解您的代码)。也就是说,每个作者从一篇文章开始。当在 allArticles 中再次找到该文章时,该文章的作者就会将该文章添加到他们的文章列表中。
  • @tonydanza:你没有足够的声望来“聊天”。让我们这样做——在上面编辑您的代码,然后删除您的回复。我也会这样做,我们会再做一些。 cmets 中的格式很糟糕,但你写的 =should= 工作。除了由于格式错误我可能看不到错误...
  • @tonydanza:您可能也需要这样做,但要准备好查找错误或在 addArticle() 中查找错误,具体取决于编写方式。发布更多代码怎么样?在这个现在很长的讨论中删除你的回复。
  • 好的,朱莉,我定义了 Article.equals 方法,现在它可以工作了。谢谢!
【解决方案2】:

对于不同但等效的 Author 实例,您需要覆盖 Author.equals() 以返回 true

【讨论】:

  • 我试过了:public boolean equals(Author a) { return this.getName().equals(a); } 但它不起作用。
  • @tonydanza:那是因为getName()string)永远不会等于aAuthor)。此外,您需要覆盖 equals(),它采用Object
  • 知道了,但还是不行。我的方法是public boolean equals(Object a) { Author aut = (Author)a; return this.getName().equals(aut.getName()); },但我让所有作者都有两篇重复的文章,比如作者 x:文章“Title1”,文章“Title1”。
  • @SLaks:逻辑也很糟糕。即使修复了 equals() 方法,代码仍然会被破坏。事实上,修复 equals() 方法会破坏代码——现在可以删除列表中以前的 Author 对象,因为它可以比较等于。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多