リスト反復子は、何よりもまず、リストの要素をリストの内部順序(別名挿入順序)で取得することを保証します。より具体的には、要素を挿入した順序、またはリストの操作方法です。並べ替えはデータ構造の操作と見なすことができ、リストを並べ替える方法はいくつかあります。
私は個人的にそれを見て、有用性の順に方法を並べます。
1. 代わりにSet
またはBag
コレクションの使用を検討してください
注:これは通常、とにかくやりたいことなので、このオプションを一番上に置きます。
ソートされたセットは、挿入時にコレクションを自動的にソートします。つまり、コレクションに要素を追加するときにソートを実行します。また、手動で並べ替える必要もありません。
さらに、重複する要素について心配する必要がない(または持つ必要がない)場合は、TreeSet<T>
代わりに使用できます。それは実装SortedSet
してNavigableSet
インターフェースし、おそらくリストから期待するように動作します:
TreeSet<String> set = new TreeSet<String>();
set.add("lol");
set.add("cat");
// automatically sorts natural order when adding
for (String s : set) {
System.out.println(s);
}
// Prints out "cat" and "lol"
自然な順序付けが必要ない場合は、をとるコンストラクタパラメータを使用できますComparator<T>
。
別の方法としては、使用することができます複数セット(としても知られているバッグ)で、Set
代わりに、要素の重複を可能にし、それらのサードパーティの実装があります。特にグアバのライブラリには、TreeMultiset
とよく似たがありTreeSet
ます。
2.リストを並べ替えます Collections.sort()
上記のように、List
sのソートはデータ構造の操作です。したがって、さまざまな方法で並べ替えられる「1つの信頼できる情報源」が必要な状況では、手動で並べ替えるのがよいでしょう。
java.util.Collections.sort()
メソッドでリストを並べ替えることができます。方法のコードサンプルは次のとおりです。
List<String> strings = new ArrayList<String>()
strings.add("lol");
strings.add("cat");
Collections.sort(strings);
for (String s : strings) {
System.out.println(s);
}
// Prints out "cat" and "lol"
コンパレーターの使用
1つの明確な利点はComparator
、sort
メソッドで使用できることです。Java は、ロケール依存のソート文字列に役立つComparator
などの実装もいくつか提供してCollator
います。以下はその一例です。
Collator usCollator = Collator.getInstance(Locale.US);
usCollator.setStrength(Collator.PRIMARY); // ignores casing
Collections.sort(strings, usCollator);
並行環境でのソート
ただしsort
、コレクションのインスタンスは操作されるため、メソッドの使用は並行環境では使いにくいため、代わりに不変コレクションの使用を検討する必要があります。これは、グアバがOrdering
クラスで提供するものであり、単純なワンライナーです:
List<string> sorted = Ordering.natural().sortedCopy(strings);
3.リストをラップして java.util.PriorityQueue
Javaにはソートされたリストはありませんが、ソートされたキューがあり、おそらく同じように機能します。これは、あるjava.util.PriorityQueue
クラス。
ニコ・ハーセは、これにも答える関連質問へのコメントにリンクしました。
並べ替えられたコレクションでは、内部データ構造を操作したくない場合がほとんどです。そのため、PriorityQueueはListインターフェースを実装していません(その要素に直接アクセスできるためです)。
PriorityQueue
イテレータに関する注意
PriorityQueue
クラスの実装Iterable<E>
とCollection<E>
、それはいつものように繰り返すことができるようにインターフェイス。ただし、イテレータは、ソートされた順序で要素を返すことが保証されていません。代わりに(Alderathがコメントで指摘しているように)poll()
、空になるまでキューに入れる必要があります。
任意のコレクションを取得するコンストラクタを介して、リストを優先度キューに変換できることに注意してください。
List<String> strings = new ArrayList<String>()
strings.add("lol");
strings.add("cat");
PriorityQueue<String> sortedStrings = new PriorityQueue(strings);
while(!sortedStrings.isEmpty()) {
System.out.println(sortedStrings.poll());
}
// Prints out "cat" and "lol"
4.独自のSortedList
クラスを作成する
注:これを行う必要はありません。
新しい要素を追加するたびにソートする独自のListクラスを作成できます。これは、実装によってはかなり重い計算になる可能性があり、2つの主な理由により、演習として実行したくない場合を除いて無意味です。
- メソッドは、ユーザーが指定したインデックスに要素が存在することを保証する必要
List<E>
があるため、インターフェイスのコントラクトにadd
違反します。
- なぜ車輪を再発明するのですか?上記の最初のポイントで指摘したように、代わりにツリーセットまたはマルチセットを使用する必要があります。
ただし、ここで演習としてそれを実行したい場合は、開始するためのコードサンプルであり、AbstractList
抽象クラスを使用します。
public class SortedList<E> extends AbstractList<E> {
private ArrayList<E> internalList = new ArrayList<E>();
// Note that add(E e) in AbstractList is calling this one
@Override
public void add(int position, E e) {
internalList.add(e);
Collections.sort(internalList, null);
}
@Override
public E get(int i) {
return internalList.get(i);
}
@Override
public int size() {
return internalList.size();
}
}
必要なメソッドをオーバーライドしていない場合、デフォルトの実装からAbstractList
がスローされることに注意してくださいUnsupportedOperationException
。