左右に並べ替える必要があるコレクション (List<Rectangle>) があります。その部分は簡単です。次に、元の順序でRectangles を反復処理したいのですが、並べ替えられたコレクションでインデックスを簡単に見つけることができます。多数の等しいオブジェクトがある可能性があるため、indexOf() は機能しません。これを行う簡単な方法があるはずだと感じずにはいられません。
4 に答える
私は解決策を見つけました-しかし、おそらくそこにはもっときちんとした/より最適なものがあります。
List<Rectangle> originalRects = ...;
/* record index of each rectangle object.
* Using a hash map makes lookups efficient,
* and using an IdentityHashMap means we lookup by object identity
* not value.
*/
IdentityHashMap<Rectangle, Integer> originalIndices = new IdentityHashMap<Rectangle, Integer>();
for(int i=0; i<originalRects.size(); i++) {
originalIndices.put(originalRects.get(i), i);
}
/* copy rectangle list */
List<Rectangle> sortedRects = new ArrayList<Rectangle>();
sortedRects.addAll(originalRects);
/* and sort */
Collections.sort(sortedRects, new LeftToRightComparator());
/* Loop through original list */
for(int i=0; i<sortedRects.size(); i++) {
Rectangle rect = sortedRects.get(i);
/* Lookup original index efficiently */
int origIndex = originalIndices.get(rect);
/* I know the original, and sorted indices plus the rectangle itself */
...
何万ものオブジェクトがない場合は、それらを 2 つの別個のコレクション (1 つは元のコレクション、もう 1 つはソート済み) に格納することができます。Java のコレクション クラスはオブジェクトへの参照のみを格納するため、見かけほど多くのメモリを消費しないことに注意してください。
もう 1 つの方法は、元のリストをソートする代わりに、インデックスの配列をソートすることです。配列は、ID 配列 a[0] = 0、a[1] = 1 などとして開始し、カスタム コンパレータ/ソートを使用してインデックス配列を取得します。別のコレクションではなく整数の余分な配列しかないため、余分なスペースは必要ありません。
リストを複製し、そのうちの 1 つを並べ替えます。同じオブジェクトへの 2 つの参照を持つことは、同じオブジェクトへのポインターが同じであり、それらを見分けることができないため、indexOf() ではあまり問題になりません。等しいが同一ではない 2 つのオブジェクトがあり、それらを区別したい場合は、 indexOf() が equal メソッドを使用しているため、問題が発生します。この場合、最善の解決策は、リストを単純に反復処理して、オブジェクトの同一性 (==) をチェックすることです。