【问题标题】:ArrayList removeAll() not removing objectsArrayList removeAll() 不删除对象
【发布时间】:2016-06-27 21:12:18
【问题描述】:

我有成员类的简单ArrayLists:

ArrayList<Member> mGroupMembers = new ArrayList<>();
ArrayList<Member> mFriends = new ArrayList<>();

会员等级:

public class Member {
    private String userUID;
    private String userName;

    public String getUserUID() {
        return userUID;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setUserUID(String userUID) {
        this.userUID = userUID;
    }


}

朋友的 ArrayList 包含所有用户的朋友。我只是想做的就是从朋友列表中删除组成员,如果存在的话:

mFriends.removeAll(mGroupMembers);

但它对mFriends 列表没有任何作用...

查看日志语句,该朋友确实出现在mGroupMember 列表中。

为什么这不起作用?

【问题讨论】:

  • 由于我在Member 类中看不到覆盖equals 方法,我怀疑您的列表不包含相同的对象,而只包含相似的对象(具有相似的状态)。
  • 您的问题中没有包含足够的信息,但猜测您的列表中有不同的(但等效的)Member 对象。正如 Pshemo 所说,由于您尚未为 Member 定义 equals,因此它将使用 Objectequals,而对于等效的 Member 对象则不是这样。您需要覆盖equals(因此也需要覆盖hashCode)。

标签: java android arraylist


【解决方案1】:

如何确定两个成员相等?我猜它们是否具有相同的 ID,您认为它们相等,但是 java 希望它们在内存中是完全相同的引用,但情况可能并非如此。要更正此问题,您可以覆盖 equals 函数以使其在 id 相等时返回:

public class Member {
    //..

    @Override
    public boolean equals(Object anObject) {
        if (!(anObject instanceof Member)) {
            return false;
        }
        Member otherMember = (Member)anObject;
        return otherMember.getUserUID().equals(getUserUID());
    }
}

此外,当您覆盖.equals 时,建议您也覆盖hashCode,以便对象在SetMap 等散列函数中也能正常工作。

【讨论】:

  • Member 对象中的等号是否被覆盖?
  • @TJCrowder 也不要忘记检查anObject 是否是该类的实例。
  • @Sauron 是的,它会在你的 Member 类中被覆盖。还要注意编辑,因为 userID 是一个字符串,它需要是.equals。而不是==
  • @KevinDiTraglia,是的,这就是我忘记的。
  • @KevinDiTragila 无需检查它是否为空。 instanceof 在给它一个空值时总是给它 false。
【解决方案2】:

如 cmets 中所述,ArrayList 中的元素只有在其 equals() 方法返回 true 时才会被删除。非覆盖方法根据引用检查相等性(即它们必须是内存中的同一个对象)。

您可能想要基于Member 的属性覆盖equals,如下例所示:

@Override
public void equals(Object o) {
    if(o == null) {
        return false;
    } else if (!(o instanceof Member)) {
        return false;
    } else {
        return ((Member) o).getUserUID().equals(this.userUID) && ((Member) o).getUserName().equals(this.userName);
    }
}

另外,你应该在覆盖equals()的时候覆盖hashCode(),这样当两个对象相等时,它们就有相同的哈希码。 hashCode 的非覆盖实现也是基于引用相等。

【讨论】:

    【解决方案3】:

    你必须知道

    ArrayList#removeAll(Collection)

    打电话给

    ArrayList#contains(Object)

    调用

    ArrayList#indexOf(Object)

    最终调用

    Object#equals


    因此,如果 equals 未被正确覆盖 (following the equals contract rules),您将无法获得正确的行为。

    【讨论】:

    • 这很容易理解。我更喜欢这个答案,而不是这里提供的实际代码,因为它解释了比较不起作用的原因。
    • @YogendraJ 非常感谢 :) 很高兴它有帮助
    猜你喜欢
    • 2014-09-28
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    相关资源
    最近更新 更多