【问题标题】:Java "contains" not working properlyJava“包含”无法正常工作
【发布时间】:2016-10-03 12:45:00
【问题描述】:

我的班级:

public class UserProgressModel {

    private String email;

    public UserProgressModel(String pEmail) {
        super();

        this.email = pEmail;
    }

    @Override
    public boolean equals(Object x) {

        if (x != null && x instanceof UserProgressModel
                && ((UserProgressModel) x).email.equals(this.email) == true) {

            return true;
        }

        if (x != null && x instanceof String
                && x.equals(this.email) == true) {

            return true;
        }

        return false;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 17 * hash + (this.email != null ? this.email.hashCode() : 0);
        return hash;
    }
}

在通过 gson 放置一些对象之后:

UserProgressModel[] userProgressArray;
List<UserProgressModel> retUserProgress = new ArrayList<>();

userProgressArray = gs.fromJson(fileContents,
                        new TypeToken<UserProgressModel[]>() {
                        }.getType());

for (UserProgressModel ele : userProgressArray) {

    if (ele != null) {
        retUserProgress.add(ele);
    }
}

我无法验证以下代码:

retUserProgress.contains("test@test.com");

我遍历数组以验证一个对象是否有电子邮件。

我做得对吗?我想我已经覆盖了等号和哈希码。

【问题讨论】:

  • 让您的UserProgressModel.equals(...) 告诉您该对象等于String 不符合equals 方法的一般约定。 UserProgressModel 并不是真正“等于”字符串。此外,myString.equals(myUserProgressModel) 将始终返回 false,因此您正在创建一个不对称的平等。此外,您的字符串和模型实例将具有不同的哈希码,因此它们不应假装相等。
  • retUserProgress 是一个 List... 不是直接 UserProgressModel ,所以也许这就是问题。

标签: java android gson overriding contains


【解决方案1】:

您的 equals 实现不正确。如果你查看 equals 的合约,实现必须是对称的:

... for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true. 

在您的情况下,您有一个 UserProgressModel 对象列表,但您正在尝试与字符串进行比较。虽然您已经实现了 UserProgressModel.equals(String) ,但您仍然需要让 String.equals(UserProgressModel) 返回正确的结果。因为你不能这样做,所以这个实现永远不会在所有情况下都有效。你应该做的是两件事:

删除对 String 的 equals 的检查,因为它永远不会起作用。

使用模拟对象签入集合:

retUserProgress.contains(new UserProgressModel("test@test.com"));

只要您的 equals 方法在您自己的类型 (UserProgressModel.equals(UserProgressModel)) 中是正确的,这应该可以解决您的问题。

【讨论】:

    【解决方案2】:

    您无法检查 retUserProgress 是否包含电子邮件,因为它不包含。 ArrayList 包含 Class: UserProgressModel 的对象,因此您可以检查 ArrayList 是否包含“UserProgressModel”。

    你想做的是以下

    private boolean containsEmail(List<UserProgressModel> retUserProgress, String email) {
        boolean result = false;
    
        for (UserProgressModel object : retUserProgress) {
            if (object.equals(email))
                result = true;
        }
    
        return result;
    }
    

    然后像这样调用方法:

    containsEmail(retUserProgress, "test@test.com"); //This will return a true or false, depending if the ArrayList retUserProgress contains the email
    

    【讨论】:

      【解决方案3】:

      我已经在 ideone 中测试过你的代码

      它正在工作

      true

      UserProgressModel model=new UserProgressModel("test@test.com");
      System.out.print(model.equals("test@test.com"));
      

      false

      UserProgressModel model=new UserProgressModel("test@test.com");
      System.out.print(model.equals("test@test.co"));
      

      尝试与新对象进行比较

      retUserProgress.contains(new UserProgressModel("test@test.com"))
      

      result

      如果您不想与新的 UserProgressModel 进行比较,则需要创建自己的列表类型,当它比较两个对象(UserProgressModel、字符串)时,它会创建一个新的 UserProgressModel 并为其传递该电子邮件

      【讨论】:

        猜你喜欢
        • 2017-06-12
        • 2019-04-01
        • 2019-03-01
        • 2019-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-07
        • 1970-01-01
        相关资源
        最近更新 更多