从java列表中删除相等项

从java列表中删除相等项,java,collections,Java,Collections,我有一个项目列表,其中每个项目都是一个包含2个公共字符串的简单类。 我有一个equals方法,它只对两个字符串使用字符串的equalsIgnoreCase方法 public class data { public String a; public String b; public boolean equals(data d) { if(a.equalsIgnoreCase(d.a) && b.equalsIgnoreCase(d.

我有一个项目列表,其中每个项目都是一个包含2个公共字符串的简单类。 我有一个equals方法,它只对两个字符串使用字符串的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;
        }
    }
}

有更好的方法吗?

最清晰的方法是不使用任何循环调用列表的方法,并在对象中传递参数。它使用您在对象上定义的equals方法查找并删除列表中存在的对象

_list.remove(data);
您也不必指定hashcode方法,但应该养成在覆盖equals方法时始终创建一个方法的习惯,以防在集合(如集合或映射)中使用它。

一些注释:

  • 您的
    equals
    方法不会覆盖
    对象的
    equals
    方法(参数应为
    对象
    类型,而不是
    数据
    类型)
  • 您应该改进
    equals
    方法来解释空值等
  • 最后,当您重写
    equals()
    时,您也应该重写
    hashcode()
    ——否则,您可能会在使用集合或映射时遇到一些奇怪的行为
如果正确重写
equals
方法,则只需使用
remove
方法即可。 请参见下面由Netbeans生成的自动生成的
equals
hashcode
,并修改为使用
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;
    }

}
publicstaticvoidmain(字符串[]args){
列表=新的ArrayList();
增加(新数据(“a”、“b”));
增加(新数据(“a”、“c”));
System.out.println(list.size());//2
删除(新数据(“A”、“b”));
System.out.println(list.size());//1
}
公共静态类数据{
公共字符串a;
公共字符串b;
公共数据(字符串a、字符串b){
这个a=a;
这个.b=b;
}
@凌驾
公共布尔等于(对象obj){
if(obj==null)返回false;
如果(getClass()!=obj.getClass())返回false;
最终数据其他=(数据)obj;
布尔sameA=(this.a==other.a)| |(this.a!=null&&this.a.equalsIgnoreCase(other.a));
如果(!sameA)返回false;
布尔sameB=(this.b==other.b)| |(this.b!=null&&this.b.equalsIgnoreCase(other.b));
如果(!sameB)返回false;
返回true;
}
@凌驾
公共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());
返回散列;
}
}

根据顺序对你的集合有多重要,你可以考虑使用一个映射,比如A。这样,您就可以通过键查找对象。这比使用循环要好,但并非总是必需的。列表不是此练习的最佳容器。他的equals方法不会重写Object。equals因此remove将无法按预期工作。这是一个多么好的捕获!@Override注释再次证明了它的用途。非常感谢您快速完整的回答!这非常有用。这是一种合适的方法(覆盖equals,以及hashCode,它应该总是与equals一起覆盖),但是上面自动生成的equals与他使用的equals不匹配(他可以重新实现)@pickypg我已经修改了accordingly@assylias:如果重写
equals()
,那么重写
hashCode()
不仅是一种好的做法,而且是这些方法的契约所要求的。尽管像
List
这样的非散列集合即使没有正确覆盖
hashCode()
也可以正常工作,但其他数据结构不会。