【问题标题】:LinkedHashSet not removingLinkedHashSet 未删除
【发布时间】:2017-03-17 12:24:18
【问题描述】:

我遇到了一种奇怪的行为,我不知道为什么。我尝试从LinkedHashSet 中删除一个元素,但它没有被删除。

我的班级文档已定义:

protected Set<Author> authors = new LinkedHashSet<>();

那么当idrole 相等时Author 相等::

@Override
public int hashCode() {
    int hash = 7;
    hash = 53 * hash + Objects.hashCode(this.id);
    hash = 53 * hash + Objects.hashCode(this.role);
    System.out.println("Calling hashcode: " + hash);
    return hash;
}

@Override
public boolean equals(Object obj) {
    System.out.println("Calling equals");
    if (obj == null) {
        return false;
    }
    System.out.println("1");
    if (getClass() != obj.getClass()) {
        return false;
    }
    System.out.println("2");
    final Author other = (Author) obj;
    if (!Objects.equals(this.id, other.id)) {
        return false;
    }
    System.out.println("3");
    if (!Objects.equals(this.role, other.role)) {
        return false;
    }
    System.out.println("4");
    return true;
}

然后是通过一些调试打印删除的代码:

public void removeAuthor(Author author) {
    System.out.println(">removeAuthor [" + author.hashCode() + "]: " + author);
    if (document.getAuthors() != null) {
        System.out.println("[" + document.getAuthors().size() + "] Authors BEFORE:");
        document.getAuthors().forEach((pp) -> {
            System.out.println("[" + pp.hashCode() + "] " + pp);
        });
    }

    if (document != null) {
        if (document.getAuthors() != null) {
            document.getAuthors().remove(author);
        }
    }

    if (document.getAuthors() != null) {
        System.out.println("[" + document.getAuthors().size() + "] Authors AFTER:");
        document.getAuthors().forEach((pp) -> {
            System.out.println("[" + pp.hashCode() + "] " + pp);
        });
    }
}

这会打印以下内容(我添加了我的 cmets):

// Call to hashCode() to print the author that will be removed
    Calling hashcode: 400605768   
// Author that will be removed
    >removeAuthor [400605768]: Author{id=self, name=Self Centre, forename=null, familyName=null, role=Writer} 
// List before calling remove, it gives 2 authors
    [2] Authors BEFORE:
    Calling hashcode: -1820871746
    [-1820871746] Author{id=self, name=Self Centre, forename=null, familyName=null, role=Researcher}
    Calling hashcode: 400605768
    [400605768] Author{id=self, name=Self Centre, forename=null, familyName=null, role=Writer}
// This hashCode call is probably done by remove(). As it can be seen, the object to be removed *is* on the Set
    Calling hashcode: 400605768
// List after calling remove, it gives again 2 authors
    [2] Authors AFTER:
    Calling hashcode: -1820871746
    [-1820871746] Author{id=self, name=Self Centre, forename=null, familyName=null, role=Researcher}
    Calling hashcode: 400605768
    [400605768] Author{id=self, name=Self Centre, forename=null, familyName=null, role=Writer}
    Calling hashcode: -1820871746

我通常习惯于使用集合。这可能是一个愚蠢的错误,但我找不到它在哪里。此外,compareTo 或其他方法似乎不用于测试相等性。

【问题讨论】:

  • 你能构造一个minimal test-case吗?
  • 调用 contains 方法时所拥有的。 document.getAuthors().contains(author) ?
  • Author.role 是什么类型?如果它是一个自定义类,它是否也实现了equals?
  • 作者角色是一个字符串,和id一样。但是equals似乎没有被调用
  • System.out.println("contains " + document.getAuthors().contains(author)); 返回contains false

标签: java data-structures collections


【解决方案1】:

我想我已经解决了这个问题,感谢调试。这是 Ajax 使用中的一个明显错误。创建LinkedHashSet 时,将元素添加到基于其hashCode 的索引中的哈希表中。有时,Ajax JSF 操作可以更改内存中对象的role,从而使它们更改其哈希值。但是,它们在哈希表中最初插入的位置根本没有改变!因此,您现在有一个要删除的具有特定哈希的元素,该元素确实存在于您的 Set 中(如所见,哈希相同)但是当实际代码尝试从 table[ (table.length-1) &amp; hash ] 中删除该元素时,它永远不会找到,因为它不在那个位置 - 它最初添加了另一个哈希值。这解决了这个谜团,这是完全合乎逻辑的。

【讨论】:

  • 其实没那么严重。只是一些 ajax 方法允许更改角色(以及其他属性),这是完全明智的,而且它们恰好是关键的一部分。因此,当发生这种变化时,应该删除并重新插入 set 元素。
  • 现在尽在掌握之中。谢谢! = )
猜你喜欢
  • 1970-01-01
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-02
  • 2011-07-02
相关资源
最近更新 更多