63

Setインデックス値に基づいてからオブジェクトを取得することについて他の質問を見てきましたが、それが不可能な理由を理解しています。しかし、オブジェクトによる取得が許可されていない理由についての適切な説明を見つけることができなかったので、私が尋ねると思いました。

HashSetがサポートしているHashMapので、そこからオブジェクトを取得するのは非常に簡単です。現在のように、の各項目を繰り返し処理して、HashSet不必要と思われる同等性をテストする必要があるようです。

を使用することもできますMapが、key:valueのペアは必要ありません。必要なのは、だけですSet

たとえば、私が持っていると言うFoo.java

package example;

import java.io.Serializable;

public class Foo implements Serializable {

    String _id;
    String _description;

    public Foo(String id){
        this._id = id
    }

    public void setDescription(String description){
        this._description = description;
    }

    public String getDescription(){
        return this._description;
    }

    public boolean equals(Object obj) {
        //equals code, checks if id's are equal
    }

    public int hashCode() {
        //hash code calculation
    }

}

およびExample.java

package example;

import java.util.HashSet;

public class Example {

    public static void main(String[] args){
        HashSet<Foo> set = new HashSet<Foo>();

        Foo foo1 = new Foo("1");
        foo1.setDescription("Number 1");

        set.add(foo1);
        set.add(new Foo("2"));

        //I want to get the object stored in the Set, so I construct a object that is 'equal' to the one I want.
        Foo theFoo = set.get(new Foo("1")); //Is there a reason this is not allowed?
        System.out.println(theFoo.getDescription); //Should print Number 1
    }

}

equalsメソッドは、「論理的」な同等性ではなく「絶対的な」同等性をテストすることを目的としているためですcontains(Object o)か(この場合は十分です)。

4

11 に答える 11

30

ASetは重複としてCollection扱うオブジェクトの であるa.equals(b) == trueため、既に持っている同じオブジェクトを取得しようとしても意味がありません。

get(Object)コレクションから取得しようとしている場合は、 a のMap方が適している可能性があります。

あなたが書くべきことは、

Map<String, String> map = new LinkedHashMap<>();

map.put("1", "Number 1");
map.put("2", null);
String description = map.get("1");

オブジェクトがセット内にない場合 (equals に基づく)、追加します。セット内にある場合 (equals に基づく)、そのオブジェクトのセットのインスタンスを教えてください。

万一、これが必要になった場合は、Map.

Map<Bar, Bar> map = // LinkedHashMap or ConcurrentHashMap

Bar bar1 = new Bar(1);
map.put(bar1, bar1);

Bar bar1a = map.get(new Bar(1));
于 2012-12-13T15:56:31.977 に答える
5

あなたの最後の文が答えです。

get(Object o)(メソッドを使用して)等しい別のオブジェクトをHashSet探します。したがって、実際には と同じですが、同じ結果を返さないだけです。oequals(o)contains(o)

于 2012-12-13T15:58:09.437 に答える
4

new Foo("1");オブジェクトが既に存在することを知りたい場合は、メソッドを次のsetように使用する必要があります。contains

boolean present =  set.contains(new Foo("1"));

メソッドのget種類 ieset.get(new Foo("1"));は意味がないためサポートされていません。あなたはすでにオブジェクトを持っていnew Foo("1")ますget.

于 2012-12-13T15:59:34.647 に答える
0

get がない理由は単純です。

セットからオブジェクト X を取得する必要がある場合は、X から何かが必要であり、オブジェクトを持っていないためです。

オブジェクトを持っていない場合は、それを見つけるための何らかの手段 (キー) が必要です。..その名前、番号は何でも。それが正しいマップです。

map.get( "キー" ) -> X!

セットにはキーがありません。オブジェクトを取得するにはそれらをトラバースする必要があります。

では、便利な get( X ) -> X を追加してみませんか?

あなたはすでにXを持っているので、それは意味がありません、と純粋主義者は言います。

しかし、今はそれを非純粋主義者として見て、本当にこれが必要かどうかを確認してください:

オブジェクト Y を作成するとします。これは、X に等しいものと一致するため、set.get(Y)->X となります。ヴォリア、それなら私が持っていなかった X のデータにアクセスできます。たとえば、X に get flag() というメソッドがあり、その結果が必要だとします。

このコードを見てください。

X = map.get( Y );

Y.equals( x ) は真です!

しかし..

Y.flag() == X.flag() = false. (彼らは対等ではなかったのですか?)

ですから、 set がそのようなオブジェクトを取得できるようにした場合、それは確かに equals の基本的なセマンティックを壊すことになります。後で、X の小さなクローンと一緒に暮らすことになります。

ものを保存し、キーを使用してそれを取得するには、マップが必要です。

于 2015-03-05T20:15:36.607 に答える
0

HashSet は HashMap よりも少し単純です。HashMap の機能が必要ないのに、なぜそれを使うのでしょうか? getObject(ObjectType o) のようなメソッドが Java によって実装されている場合、contain() メソッドを呼び出した後にセットを反復処理する必要はありません...

于 2014-07-19T16:41:31.330 に答える
0

私はスレッドの作成者と同じ問題を抱えており、Set に get メソッドが必要な本当の理由があります。たとえば、セット Set の内容である X の equals を上書きしたため、含まれるオブジェクトは必ずしもチェックしたものと同じ。私のシナリオでは、他のコレクションのセマンティック ダブルを削除し、「オリジナル」を「ダブル」の関係で強化するため、ダブルを削除できるようにするには「オリジナル」が必要です。

于 2019-11-07T15:44:08.330 に答える
-1

誰もが前に述べたように、そのような方法はなく、正当な理由があります。そうは言っても、(ほぼ)ワンライナーを使用してJava 8のHashSetから特定のオブジェクトを取得したい場合は、単にストリームを使用してください。あなたの場合、それは次のようになります:

Foo existing = set.stream().filter(o -> o.equals(new Foo("1"))).collect(Collectors.toList()).iterator().next();

要素が存在しない場合は例外がスローされるため、技術的にはワンライナーではありませんが、フィルターが適切に実装されている場合は、コレクション要素に対する従来の反復よりも高速になるはずです。

于 2015-01-02T09:48:09.223 に答える