1

LinkedHashMap<Foo, Double>最初のフィールドがオブジェクトで、2 番目のフィールドが測定の原点からの距離であるa で表される線に沿って設定された一連のオブジェクトがあります。要素が距離の昇順で並べられていることを知っています。ある位置を選択し、マップ全体をトラバースすることなく、戻る場所xのインスタンスを左右に検索できるようにしたいと考えています。Foofoo.isInteresting()true

私の最初のアイデアは、次のようなことです。

  • すべてのエントリを反復して、距離がより大きい最初のエントリを見つけますx
  • この時点から、すべてのエントリを左に見てください。foo.isInteresting()
  • この時点から、すべてのエントリを右に見てください。foo.isInteresting()

しかし、私が知る限りMap、特定の開始点から反復する方法はありません。Listマップから 2 つのオブジェクトを作成して を使用するのは賢明でしょうListIteratorか?

Fooまた、アプリケーションの他の場所で検索する必要があるため、キーと値を交換することはあまり賢明ではありません。

4

6 に答える 6

1

代わりに、ナビゲート可能なマップまたはツリーマップtailmapが役立つ場合があります。具体的には、およびsubmapメソッド

于 2012-07-26T14:01:54.783 に答える
1

を使用しTreeSet<Foo>、内部で距離を保ちFoo、コンパレーターを準備できます。Foo と distance を含み、比較可能なラッパー オブジェクトを作成して、TreeSet<Wrapper>. lower次に、 とhigherのメソッドを使用できますNavigableSet

class Wrapper implements Comparable<Wrapper> {

    public Foo foo;
    public Double distance;

    public Wrapper(Foo foo, Double distance) {
        this.foo = foo;
        this.distance = distance;
    }

    /**
     * Use only Foo for hashcode and equals 
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((foo == null) ? 0 : foo.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;
        Wrapper other = (Wrapper) obj;
        if (foo == null) {
            if (other.foo != null)
                return false;
        } else if (!foo.equals(other.foo))
            return false;
        return true;
    }

    @Override
    public int compareTo(Wrapper o) {
        return distance.compareTo(o.distance);
    }

}@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Wrapper other = (Wrapper) obj;
    if (foo == null) {
        if (other.foo != null)
            return false;
    } else if (!foo.equals(other.foo))
        return false;
    return true;
}

@Override
public int compareTo(Wrapper o) {
    return distance.compareTo(o.distance);
}

}

これにより、Foo で検索し、距離で並べ替えることができます。

于 2012-07-26T14:08:22.620 に答える
1

Mapここで選択するデータ型を a にするべきではないと思います。代わりに、 を作成し、ArrayList<Foo>原点からの距離をコンパレータとして使用して並べ替えます。次に、 を使用Collections.binarySearch()して、目的の距離に最も近いインデックスをすばやく見つけることができます。それが完了したら、 を使用して特定の値のセットを反復処理できますList.subList()

A TreeSet( を使用TreeSet.subSet()) も同様に機能しますが、二次比較として s を比較できるようにする必要があるため (原点からの距離が 2 つの要素で等しい場合) Comparator、少し複雑にする必要があります。Foo

于 2012-07-26T14:10:12.193 に答える
0

array[2][n] または 2 つの array[n] を使用できます。最初の行は距離値で、2 番目の行はオブジェクトです。したがって、距離に従って並べ替え、二分探索を使用することができます。必要な距離の要素が見つかったら、左または右にトラバースできます。

于 2012-07-26T16:28:07.187 に答える
0

2 つの Map (同時に更新) を操作するのは悪い考えですか?

LinkedHashMap<Foo, Double> basicMap;
SortedMap<Double, Set<Foo>> distMap; // may have same Double for two 'Foo's.

編集して SortedMap で変更する

于 2012-07-26T14:19:09.723 に答える
0

indexed-tree-mapを検討すると、インデックスで要素にアクセスし、ソート順を維持しながら要素のインデックスを取得できます。重複は、同じキーの下の値として配列に入れることができます。

于 2013-02-10T22:06:15.407 に答える