Comparable <>を使用して「自然な並べ替え順序」を定義するオブジェクトがあります。これらはTreeSetsに保存されています。
オブジェクトを削除して再追加する以外に、ソート順の定義に使用されるメンバーが更新されたときにソートを更新する別の方法はありますか?
他の人が指摘したように、組み込みの方法はありません。ただし、選択したコンストラクタを使用して、常にTreeSetをサブクラス化し、必要な機能を追加できます。
_public class UpdateableTreeSet<T extends Updateable> extends TreeSet<T> {
// definition of updateable
interface Updateable{ void update(Object value); }
// constructors here
...
// 'update' method; returns false if removal fails or duplicate after update
public boolean update(T e, Object value) {
if (remove(e)) {
e.update(value);
return add(e);
} else {
return false;
}
}
}
_
それ以降は、_((UpdateableTreeSet)mySet).update(anElement, aValue)
_を呼び出して、並べ替え値と並べ替え自体を更新する必要があります。これには、追加のupdate()
メソッドをデータオブジェクトに実装する必要があります。
同様の問題があり、このスレッドとtucuxiの答え(ありがとう!)に基づいて、独自のUpdateableTreeSet
を実装しました。私のバージョンは
UpdateableTreeSet
は、ユーザーから多くの複雑さを隠します。一括更新/削除の遅延に加えて、tucuxiで示される単一要素の更新/削除は、引き続きクラスで使用できます。
更新2012-08-07:このクラスは、少しだけ利用可能です GitHubリポジトリ 導入を含むREADME回路図サンプルコードと方法を示す単体テスト(ない))より詳細に使用します。
Set
を本当に使用する必要がある場合は、運が悪いと思います。
ただし、ワイルドカードを使用します-List
の代わりにSet
を使用するのに十分な柔軟性がある場合は、Collections.sort()
を使用してList
をオンデマンドで再ソートします。 List
順序をあまり変更する必要がない場合、これはパフォーマンスが高いはずです。
Apple iPhoneホイールスクロールに似た動的スクロールペインを実装しようとしたときに、この問題を調べました。TreeSet
のアイテムはこのクラスです。
/**
* Data object that contains a {@code DoubleExpression} bound to an item's
* relative distance away from the current {@link ScrollPane#vvalueProperty()} or
* {@link ScrollPane#hvalueProperty()}. Also contains the item index of the
* scrollable content.
*/
private static final class ItemOffset implements Comparable<ItemOffset> {
/**
* Used for floor or ceiling searches into a navigable set. Used to find the
* nearest {@code ItemOffset} to the current vValue or hValue of the scroll
* pane using {@link NavigableSet#ceiling(Object)} or
* {@link NavigableSet#floor(Object)}.
*/
private static final ItemOffset ZERO = new ItemOffset(new SimpleDoubleProperty(0), -1);
/**
* The current offset of this item from the scroll vValue or hValue. This
* offset is transformed into a real pixel length of the item distance from
* the current scroll position.
*/
private final DoubleExpression scrollOffset;
/** The item index in the list of scrollable content. */
private final int index;
ItemOffset(DoubleExpression offset, int index) {
this.scrollOffset = offset;
this.index = index;
}
/** {@inheritDoc} */
@Override
public int compareTo(ItemOffset other) {
double d1 = scrollOffset.get();
double d2 = other.scrollOffset.get();
if (d1 < d2) {
return -1;
}
if (d1 > d2) {
return 1;
}
// Double expression has yet to be bound
// If we don't compare by index we will
// have a lot of values ejected from the
// navigable set since they will be equal.
return Integer.compare(index, other.index);
}
/** {@inheritDoc} */
@Override
public String toString() {
return index + "=" + String.format("%#.4f", scrollOffset.get());
}
}
DoubleExpression
は、JavaFXプラットフォームのrunLaterタスクにバインドされるまで少し時間がかかる場合があります。これが、このラッパークラスにインデックスが含まれている理由です。
scrollOffset
は常にスクロールホイール上のユーザースクロール位置に基づいて変化するため、更新する方法が必要です。通常、オフセットはアイテムのインデックス位置に関連するため、順序は常に同じです。インデックスは変更されませんが、オフセットは、ScrollPane
の現在のvValueまたはhValueプロパティからのアイテムの相対的な距離に応じて、負または正になります。
必要な場合のみオンデマンドを更新するには、Tucuciによる上記の回答のガイダンスに従ってください。
ItemOffset first = verticalOffsets.first();
verticalOffsets.remove(first);
verticalOffsets.add(first);
ここで、verticalOffsetsはTreeSet<ItemOffset>
。この更新スニペットが呼び出されるたびにセットを印刷すると、更新されていることがわかります。
オブジェクトが少しずつ変化するか、大きく変化するかを知るのに役立ちます。各変更が非常に小さい場合は、並べ替えておくリストにデータを入れると非常にうまくいきます。これを行うには、する必要があります
ただし、「あなた」を経由せずに要素を変更できないようにする必要があります。
EDIT:また! Glazed Listsは、これだけをサポートしています。
方法で構築されているのは、削除して追加し直すことだけです。