2016-05-04 16 views
0

Set.contains(Object o)はequalsを使用してオブジェクトがSetに含まれているかどうかを確認するだけで、次の2つの方法ではどのように異なる結果が得られますか?私のプロジェクトでは、メソッド1は例外をスローしませんが、メソッド2は例外をスローします。Java:Set.contains()が間違った結果を返す

詳細については、オブジェクト「グループ」がセット「グループ」に含まれているので、方法1は期待通りです。

ブールjava.util.Set.contains(オブジェクトo)

セットが、指定された要素が含まれている場合にtrueを返します。より正式には、このセットに(o == null?e == null:o.equals(e))などの要素eが含まれている場合にのみtrueを返します。

方法1:

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

方法2:

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

さらなる情報: HashSetのに使用されます。

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; 
} 
+1

どのような 'Set'実装を使用していますか? HashSet? TreeSet?他に何か? – Eran

+3

あなたのAccessControlGroup.equals実装は何ですか?あなたはそれをオーバーライドしましたか? –

+4

'AccessControlGroup'の' equals() '、' hashCode() 'の実装を見る必要があります。もしそれが 'Comparable'を実装しているのであれば、その実装を参照する必要があります(そして、Eranが言ったこと:あなたが使用しているSet実装を見なければなりません) –

答えて

0

私はあなたがセットgroupsにそれを追加した後groupを修正オッズを築くでしょう。それはhashCodeを変更し、間違ったバケットにgroupsを残します。これは、新しいhashCodeが古いものと衝突するまで、containsが見つからないことを意味します。

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

残念ながら、私はこれが起こるとは思わない。実際には、グループオブジェクトのhashCodeとHashSetの要素のhashCodeを出力しました。セット内の検索されたオブジェクトとグループオブジェクトは同じhashCodeを持ちます。 AccessControlGroupとAccessControlのequals関数を、オブジェクトが等しいかどうかにかかわらず常にtrueに戻すようにしても、containsはオブジェクトがセットにないことを示します。だから、おそらくcontainsは、このequals関数を使わないでしょうか?これはどうしたらできますか? – Elternhaus

関連する問題