【问题标题】:Remove equal item from java list从java列表中删除相等的项目
【发布时间】:2012-03-21 02:09:39
【问题描述】:

我有一个项目列表,其中每个项目都是一个包含 2 个公共字符串的简单类。 我有一个 equals 方法,它对两个字符串都使用 String 的 equalsIgnoreCase 方法。

public class data
{
    public String a;
    public String b;

    public boolean equals(data d)
    {
        if(a.equalsIgnoreCase(d.a) && b.equalsIgnoreCase(d.b))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

我希望能够删除一个元素,即使它与列表中的元素不同但等于它。

现在我正在这样做:

public void remove(data dataToRemove)
{
    for(data i : _list)
    {
        if(i.equals(dataToRemove))
        {
            _list.remove(i);
            break;
        }
    }
}

有没有更好的方法来做到这一点?

【问题讨论】:

  • 根据订单对您的收藏的重要性,您可以考虑使用地图,例如HashMap。这样你就可以通过键来查找你的对象。这比使用循环要好,但并不总是必要的。
  • 列表不是本练习的最佳容器。

标签: java collections


【解决方案1】:

几个cmets:

  • 您的equals 方法不会覆盖Objectequals 方法(参数应该是Object 类型,而不是data 类型)。
  • 您应该改进您的 equals 方法以解决空值等问题。
  • 最后,当你覆盖equals() 时,你也应该覆盖hashcode() - 否则你可能会在使用Sets 或Maps 时遇到一些奇怪的行为。

如果您正确地覆盖了equals 方法,那么您可以只使用remove 方法。 下面看Netbeans自动生成的equalshashcode,修改为使用equalsIgnoreCase方法。

public static void main(String[] args) {
    List<Data> list = new ArrayList<Data>();
    list.add(new Data("a", "b"));
    list.add(new Data("a", "c"));
    System.out.println(list.size()); //2
    list.remove(new Data("A", "b"));
    System.out.println(list.size()); //1
}

public static class Data {

    public String a;
    public String b;

    public Data(String a, String b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        final Data other = (Data) obj;
        boolean sameA = (this.a == other.a) || (this.a != null && this.a.equalsIgnoreCase(other.a));
        if (!sameA) return false;
        boolean sameB = (this.b == other.b) || (this.b != null && this.b.equalsIgnoreCase(other.b));
        if (!sameB) return false;
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 89 * hash + (this.a == null ? 0 :this.a.toUpperCase().hashCode());
        hash = 89 * hash + (this.b == null ? 0 : this.b.toUpperCase().hashCode());
        return hash;
    }

}

【讨论】:

  • 非常感谢您快速而完整的回答!很有帮助。
  • 这是适当的方法(覆盖equals,以及hashCode,它应该始终与equals一起被覆盖),但上面自动生成的equals与他使用的equals不匹配(他可以重新实现)。
  • @pickypg 我已经相应修改了
  • @assylias:如果您覆盖equals(),则覆盖hashCode() 不仅是一种好习惯,这些方法的合同也要求这样做。虽然 List 等非基于哈希的集合即使没有正确覆盖 hashCode() 也可能表现正确,但其他数据结构则不会。
【解决方案2】:

最清晰的方法是只调用列表的Remove 方法而不使用任何循环并将参数传递给您的对象。它使用您在对象上定义的 equals 方法来查找并删除它(如果它存在于列表中)。

_list.remove(data);

您也不必指定 hashcode 方法,但您应该养成在覆盖 equals 方法时始终创建一个的习惯,以防在 Set 或 Map 等集合中使用它。

【讨论】:

  • 他的 equals 方法没有覆盖 Object.equals 所以 remove 不会像他预期的那样工作。
  • 多么好的收获! @Override 注释证明它再次被使用。
猜你喜欢
  • 2019-03-22
  • 1970-01-01
  • 1970-01-01
  • 2021-03-15
  • 2015-04-02
  • 1970-01-01
  • 2022-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多