16

HashSet は、 equals メソッドがそれらが同じであると言う場合、値 1 のみを格納します。私もそう思っていました。

しかし、今、equals メソッドが true を返し、セットのサイズがまだ大きくなる HashSet に Elements を追加していますか?? すみません、混乱しています。私が間違っているいくつかのヒントはいいでしょう。

Element t1 = new Element(false, false, false, false);
Element t2 = new Element(true, true, true, true);
Element t3 = new Element(false, false, false, false);

if (t1.equals(t3))
    System.out.println("they're equal");

Set<Element> set = new HashSet<>();

set.add(t1);
set.add(t2);
set.add(t3);

System.out.println("set size: " + set.size());

この例では、私のコンソール出力は次のとおりです。

それらは等しい
セットサイズです: 3

それは私には意味がありません..サイズは2であるべきですか?

4

4 に答える 4

25

問題は、クラスがandメソッドElementをオーバーライドしていないか、これらの実装が壊れていることです。equalshashCode

Object#equalsメソッド javadocから:

equals メソッドは、null 以外のオブジェクト参照に対して等価関係を実装します。

  • これは再帰的です: null 以外の参照値 x に対して、x.equals(x) は true を返す必要があります。
  • これは対称的です: null 以外の参照値 x および y について、y.equals(x) が true を返す場合に限り、x.equals(y) は true を返す必要があります。
  • これは推移的です: null 以外の参照値 x、y、および z に対して、x.equals(y) が true を返し、y.equals(z) が true を返す場合、x.equals(z) は true を返す必要があります。一貫性があります。null 以外の参照値 x および y の場合、オブジェクトの equals 比較で使用される情報が変更されていなければ、 -x.equals(y) を複数回呼び出すと一貫して true が返されるか、一貫して false が返されます。
  • null 以外の参照値 x の場合、x.equals(null) は false を返す必要があります。

Object#hashCodeメソッド javadocから:

hashCode の一般的な契約は次のとおりです。

  • Java アプリケーションの実行中に同じオブジェクトに対して複数回呼び出された場合は常に、オブジェクトの equals 比較で使用される情報が変更されていない限り、hashCode メソッドは一貫して同じ整数を返す必要があります。この整数は、あるアプリケーションの実行から同じアプリケーションの別の実行まで一貫性を保つ必要はありません。
  • equals(Object) メソッドに従って 2 つのオブジェクトが等しい場合、2 つのオブジェクトのそれぞれで hashCode メソッドを呼び出すと、同じ整数結果が生成される必要があります。
  • equals(java.lang.Object) メソッドに従って 2 つのオブジェクトが等しくない場合、2 つのオブジェクトのそれぞれで hashCode メソッドを呼び出すと、異なる整数結果が生成される必要はありません。ただし、プログラマーは、等しくないオブジェクトに対して個別の整数結果を生成すると、ハッシュ テーブルのパフォーマンスが向上する可能性があることに注意する必要があります。

これらのメソッドの実装がこれらのルールを満たしていることを確認してください。そうすれば、Set( に裏打ちされたHashSet) が期待どおりに機能します。

于 2013-04-26T13:52:25.243 に答える
4

オブジェクトには異なるハッシュがあるため、HashSet は「入れて」から異なる「バケット」に入れます。

于 2013-04-26T13:56:07.997 に答える
4

独自のモデル クラスがある場合は、以下の例のようにいくつかの基本的な機能を変更する必要があります。

実行コード:

HashSet<MyModel> models = new HashSet<MyModel>();

for (int i = 1; i < 5; i++)
    models.add(new MyModel(i + "", "Name :" + i + ""));

for (int i = 3; i < 5; i++)
    models.add(new MyModel(i + "", "Name :" + i + ""));

for (Object object : models)
    System.out.println(object);

モデル クラス :

/**
 * Created by Arun
 */
public static class MyModel {

    private String id = "";
    private String name = "";

    public MyModel(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return getId();
    }

    @Override
    public boolean equals(Object obj) {
        return !super.equals(obj);
    }

    public int hashCode() {
        return getId().hashCode();
    }

}

お役に立てれば。

于 2015-04-20T11:31:40.953 に答える
2

はい、 FINALではないクラスのオブジェクトで実装できます。

HashSet は、オブジェクトを追加する前に 2 つのメソッドhashCode()をチェックします。equals()最初にメソッドをチェックし、Set 内のいずれかのオブジェクトと同じhashCode()ハッシュコードを返す場合は、そのオブジェクトの equals メソッドをチェックします。これは、両方のオブジェクトの参照を内部的に比較します。つまり 、これらが同じ参照である場合その場合、trueを返します。これは、値が重複していることを意味します。HashCode と equals メソッドをオーバーライドすることで、重複した非最終オブジェクトを追加できます。HashCode() では、同じパラメーターの場合に同じハッシュコードを返すことができます。this.obj1==obj

例を参照してください:

public class Product {
int i;
Product(int a)
{
    this.i=a;
}
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + i;
    return result;
}
@Override
public boolean equals(Object obj) {
    /*if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Product other = (Product) obj;
    if (i != other.i)
        return false;
    return true;*/
    return true;
}
}
`

`
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
    Product p1=new Product(1);
    Product p2=new Product(1);
    Product p3=new Product(1);
    Set s=new HashSet();
    s.add(p1);
    s.add(p2);
    s.add(p3);
    System.out.println(s.size());
}
}

出力は 1 になります。

PS:これらのメソッドをオーバーライドしないと、デフォルトの動作を使用するため、出力は 3 になります。

于 2014-09-08T10:37:34.680 に答える