简体   繁体   中英

Java: Set.contains() gives wrong result

Since Set.contains(Object o) should just use equals to check if an object is in a Set, how can the following two methods produce different results? In my project, method 1 does not throw an exception, but method 2 does throw an exception.

For information, the object "group" is in the set "groups", so Method 1 works like I would expect it.

boolean java.util.Set.contains(Object o)

Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).

Method 1:

boolean ex = true;
for (AccessControlGroup acg : groups) {
  if ((acg.equals(group))) {
    ex = false;
  }
}
if (ex) {
  throw new IllegalStateException("Invalid group");
}

Method 2:

if (!(groups.contains(group))) {
  throw new IllegalStateException("Invalid group");
}

Further information: HashSet is used.

AccessControlGroup:

public List<AccessControlGroup> getInherits() {

    if (this.inherits == null) {
      this.inherits = new ArrayList<>();
    }
    return this.inherits;
}

public void setInherits(List<AccessControlGroup> inherits) {

    this.inherits = inherits;
}

public List<AccessControlPermission> getPermissions() {

    if (this.permissions == null) {
      this.permissions = new ArrayList<>();
    }
    return this.permissions;
}

public void setPermissions(List<AccessControlPermission> permissions) {

    this.permissions = permissions;
}

@Override 
public int hashCode() {

    final int prime = 31;
    int result = super.hashCode();
    // prevent infinity loops or other sick effects
    // result = prime * result + ((this.inherits == null) ? 0 : this.inherits.hashCode());
    result = prime * result + ((this.permissions == null) ? 0 : this.permissions.hashCode());
    result = prime * result + ((this.type == null) ? 0 : this.type.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {

    if (this == obj) {
      return true;
    }
    if (!super.equals(obj)) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    AccessControlGroup other = (AccessControlGroup) obj;
    // prevent infinity loops or other sick effects...
    // if (!Objects.equal(this.inherits, other.inherits)) {
    // return false;
    // }
    if (!Objects.equals(this.permissions, other.permissions)) {
      return false;
    }
    if (!Objects.equals(this.type, other.type)) {
      return false;
    }
    return true;
    }

AccessControl:

@Override
public int hashCode() {

    final int prime = 31;
    int result = 1;
    result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {

    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    AccessControl other = (AccessControl) obj;
    if (!Objects.equals(this.id, other.id)) {
      return false;
    }
    return true;
}

I'll lay odds that you modified group after adding it to the set groups . That would change its hashCode, which would leave it in the wrong bucket in groups , which would mean contains would not find it anymore unless the new hashCode happened to collide with the old one.

Set< AccessControlGroups > groups = new HashSet<>();
AccessControlGroup group = new AccessControlGroup();
groups.add( group );
groups.contains( group ); // true
group.setPermissions( new ArrayList<>() );
groups.contains( group ); // false

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM