回答:
これは非常に遅くなりますが、JDKには、ソートされたリストを作成するためだけのクラスがあります。これは、名前が付けられています(他のSorted*
インターフェースとは多少関係がありません)java.util.PriorityQueue
。Comparable<?>
を使用して、またはを使用してソートできますComparator
。
List
ソートを使用した場合との違いCollections.sort(...)
は、ヒープデータ構造を使用することで、O(log(n))挿入パフォーマンスで常に部分的な順序を維持するのに対し、ソートでの挿入はArrayList
O(n)になることです(つまり、バイナリ検索と移動を使用して)。
ただし、とは異なりList
、PriorityQueue
はインデックス付きアクセス(get(5)
)をサポートしていません。ヒープ内のアイテムにアクセスする唯一の方法は、アイテムを一度に1つずつ取り出すことです(したがって、名前PriorityQueue
)。
TreeMapとTreeSetは、ソートされた順序でコンテンツを繰り返します。または、ArrayListを使用し、Collections.sort()を使用して並べ替えることもできます。これらのクラスはすべてjava.utilにあります
頻繁に変更するソートされたリスト(つまり、ソートされるだけでなく、複製が可能で、その要素をインデックスで効率的に参照できる構造)を維持する場合は、ArrayListを使用しますが、要素を挿入する必要がある場合、常にCollections.binarySearch()を使用して、特定の要素を追加するインデックスを決定します。後者の方法は、リストをソートされた順序に保つために挿入する必要があるインデックスを示します。
Google GuavaのTreeMultisetクラスを使用します。グアバには素晴らしいコレクションAPIがあります。
ソートされた順序を維持するListの実装を提供することに関する1つの問題は、add()
メソッドのJavaDocsで行われる約束です。
List
常にa が最後に追加する要件に言及します。
いくつかのオプションがあります。複製が不要で、挿入するオブジェクトが同等である場合は、TreeSetをお勧めします。
これを行うには、Collectionsクラスの静的メソッドを使用することもできます。
詳細については、Collections#sort(java.util.List)およびTreeSetを参照してください。
リストを並べ替えるだけの場合は、任意の種類のリストを使用して、Collections.sort()を使用します。リスト内の要素が一意で常にソートされるようにする場合は、SortedSetを使用します。
私が行ったことは、すべてのメソッドが委任された内部インスタンスを持つリストを実装することです。
public class ContactList implements List<Contact>, Serializable {
private static final long serialVersionUID = -1862666454644475565L;
private final List<Contact> list;
public ContactList() {
super();
this.list = new ArrayList<Contact>();
}
public ContactList(List<Contact> list) {
super();
//copy and order list
List<Contact>aux= new ArrayList(list);
Collections.sort(aux);
this.list = aux;
}
public void clear() {
list.clear();
}
public boolean contains(Object object) {
return list.contains(object);
}
その後、要素が存在しない場合に適切な位置に挿入する、または存在する場合に備えて置き換える新しいメソッド「putOrdered」を実装しました。
public void putOrdered(Contact contact) {
int index=Collections.binarySearch(this.list,contact);
if(index<0){
index= -(index+1);
list.add(index, contact);
}else{
list.set(index, contact);
}
}
繰り返し要素を許可する場合は、代わりにaddOrdered(または両方)を実装します。
public void addOrdered(Contact contact) {
int index=Collections.binarySearch(this.list,contact);
if(index<0){
index= -(index+1);
}
list.add(index, contact);
}
挿入を避けたい場合は、「add」および「set」メソッドでサポートされていない操作例外をスローすることもできます。
public boolean add(Contact object) {
throw new UnsupportedOperationException("Use putOrdered instead");
}
...また、ListIteratorメソッドは内部リストを変更する可能性があるため、注意が必要です。この場合、内部リストのコピーを返すか、再び例外をスローできます。
public ListIterator<Contact> listIterator() {
return (new ArrayList<Contact>(list)).listIterator();
}
List
契約に違反していることです。多分それだけを実装する方が良いでしょうCollection
。そして、ContactList
ソートされている場合は、より効率的にcontains()
使用binarySearch
することもできます。
希望どおりにソートされたリストを実装する最も効率的な方法は、次のようにインデックス付け可能なスキップリストを実装することです:Wikipedia:Indexable skiplist。O(log(n))での挿入/削除が可能になり、同時にインデックス付きアクセスが可能になります。また、重複も許可されます。
スキップリストはかなり興味深いものであり、過小評価されているデータ構造です。残念ながら、Javaベースライブラリにはインデックス付きのスキップリスト実装はありませんが、オープンソース実装の1つを使用するか、自分で実装できます。ConcurrentSkipListSetやConcurrentSkipListMapのような定期的なスキップリストの実装があります。
Java 8の以前のバージョンを使用している場合は、LambdaJでこれらのタスクを解決してみることができます。ここで見つけることができます:http : //code.google.com/p/lambdaj/
ここに例があります:
反復ソート
List<Person> sortedByAgePersons = new ArrayList<Person>(persons);
Collections.sort(sortedByAgePersons, new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
}
});
LambdaJで並べ替え
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());
もちろん、このような美しさはパフォーマンスに影響します(平均2倍)が、もっと読みやすいコードを見つけることができますか?
Collections.sort(persons, (p1, p2) -> p1.getAge().compareTo(p2.getAge()));
//or
persons.sort((p1, p2) -> p1.getAge().compareTo(p2.getAge()));
-(p1.getAge().compareTo(p2.getAge()))
PriorityQueueの問題は、単純な配列によってバックアップされ、要素を順番に取得するロジックが「queue [2 * n + 1]とqueue [2 *(n + 1)]」によって実行されることです。頭から引っ張るだけならうまくいきますが、ある時点で.toArrayを呼び出そうとすると役に立たなくなります。
私はcom.google.common.collect.TreeMultimapを使用してこの問題を回避していますが、Orderingにラップされた値のカスタムコンパレータを提供しており、0を返すことはありません。
例。ダブルの場合:
private static final Ordering<Double> NoEqualOrder = Ordering.from(new Comparator<Double>() {
@Override
public int compare(Double d1, Double d2)
{
if (d1 < d2) {
return -1;
}
else {
return 1;
}
}
});
この方法で、.toArray()を呼び出すときに値を順番に取得し、重複も取得します。
あなたが欲しいのは二分探索木です。ソートされた順序を維持しながら、検索、削除、挿入に対数アクセスを提供します(縮退したツリーがない限り、線形です)。実装は非常に簡単で、Listインターフェースを実装することもできますが、インデックスアクセスは複雑になります。
2番目の方法は、ArrayListを作成してから、バブルソートを実装することです。一度に1つの要素を挿入または削除するため、挿入と削除のアクセス時間は線形です。検索は対数であり、インデックスアクセス定数です(LinkedListでは時間が異なる場合があります)。必要なコードは、5、たぶん6行のバブルソートだけです。
ArraylistとTreemapを使用できます。繰り返し値も必要だと言ったので、TreeSetは使用できませんが、ソートもされていますが、コンパレーターを定義する必要があります。
SetにはTreeSetを使用できます。TreeSetは、その特定のオブジェクトのComparableに渡された自然順序付けまたは任意の並べ替え順序に基づいて要素を順序付けします。マップにはTreeMapを使用します。TreeMapはキーのソートを提供します。オブジェクトをキーとしてTreeMapに追加するには、そのクラスが比較可能なインターフェースを実装する必要があります。このインターフェースは、ソート順の定義を含むcompare to()メソッドを実装することを強制します。 http://techmastertutorial.in/java-collection-impl.html
以下のようにリストをソートするには、sort()メソッドを使用します。
List list = new ArrayList();
//add elements to the list
Comparator comparator = new SomeComparator();
Collections.sort(list, comparator);
参照については、リンクを参照してください:http : //tutorials.jenkov.com/java-collections/sorting.html
TreeSet
ソートされた順序で要素を与えるwhichを使用します。またはを使用Collection.sort()
した外部ソートに使用しComparator()
ます。
Java 8 Comparatorでは、リストを並べ替える場合、世界で最も人口の多い10の都市を以下に示します。時間で報告されるように、名前で並べ替えます。大阪、日本。...メキシコシティ、メキシコ。... 中国、北京。...ブラジル、サンパウロ。...ムンバイ、インド。... 中国、上海。...インド、デリー。... 東京、日本。
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class SortCityList {
/*
* Here are the 10 most populated cities in the world and we want to sort it by
* name, as reported by Time. Osaka, Japan. ... Mexico City, Mexico. ...
* Beijing, China. ... São Paulo, Brazil. ... Mumbai, India. ... Shanghai,
* China. ... Delhi, India. ... Tokyo, Japan.
*/
public static void main(String[] args) {
List<String> cities = Arrays.asList("Osaka", "Mexico City", "São Paulo", "Mumbai", "Shanghai", "Delhi",
"Tokyo");
System.out.println("Before Sorting List is:-");
System.out.println(cities);
System.out.println("--------------------------------");
System.out.println("After Use of List sort(String.CASE_INSENSITIVE_ORDER) & Sorting List is:-");
cities.sort(String.CASE_INSENSITIVE_ORDER);
System.out.println(cities);
System.out.println("--------------------------------");
System.out.println("After Use of List sort(Comparator.naturalOrder()) & Sorting List is:-");
cities.sort(Comparator.naturalOrder());
System.out.println(cities);
}
}
ユーザー定義の基準に従ってArrayListをソートします。
モデルクラス
class Student
{
int rollno;
String name, address;
public Student(int rollno, String name, String address)
{
this.rollno = rollno;
this.name = name;
this.address = address;
}
public String toString()
{
return this.rollno + " " + this.name + " " + this.address;
}
}
分類クラス
class Sortbyroll implements Comparator<Student>
{
public int compare(Student a, Student b)
{
return a.rollno - b.rollno;
}
}
メインクラス
class Main
{
public static void main (String[] args)
{
ArrayList<Student> ar = new ArrayList<Student>();
ar.add(new Student(111, "bbbb", "london"));
ar.add(new Student(131, "aaaa", "nyc"));
ar.add(new Student(121, "cccc", "jaipur"));
System.out.println("Unsorted");
for (int i=0; i<ar.size(); i++)
System.out.println(ar.get(i));
Collections.sort(ar, new Sortbyroll());
System.out.println("\nSorted by rollno");
for (int i=0; i<ar.size(); i++)
System.out.println(ar.get(i));
}
}
出力
Unsorted
111 bbbb london
131 aaaa nyc
121 cccc jaipur
Sorted by rollno
111 bbbb london
121 cccc jaipur
131 aaaa nyc