私はJavaの初心者です。 Javaでソートされたリストを維持するために使用できる/すべきコレクションを提案してください。 Map
とSet
を試しましたが、私が探していたものではありませんでした。
これは非常に遅くなりますが、ソートされたリストを持つためだけにJDKにクラスがあります。 「Sorted*
」という名前が付けられています(他のJava.util.PriorityQueue
インターフェースとは多少順不同です)。 Comparable<?>
sまたはComparator
を使用してソートできます。
Collections.sort(...)
を使用してソートされたList
との違いは、ヒープデータを使用することにより、O(log(n))挿入パフォーマンスで常に半順序を維持することです。構造体に対して、ソートされたArrayList
に挿入するとO(n)になります(つまり、バイナリ検索と移動を使用します)。
ただし、List
とは異なり、PriorityQueue
はインデックス付きアクセス(get(5)
)をサポートしません。ヒープ内のアイテムにアクセスする唯一の方法は、アイテムを取り出すことです。 time(したがって、名前PriorityQueue
)。
TreeMapとTreeSetは、ソートされた順序でコンテンツの繰り返しを提供します。または、ArrayListを使用し、Collections.sort()を使用してソートすることもできます。これらのクラスはすべてJava.utilにあります
ソート済みリストを維持する場合頻繁に変更する(つまり、ソートされることに加えて、重複を許可し、その要素をインデックスによって効率的に参照できる構造)、ArrayListを使用しますが、要素を挿入する必要がある場合は、常にCollections.binarySearch()を使用してインデックスを決定します指定された要素を追加します。後者の方法は、リストをソート順に保つために挿入する必要があるインデックスを示します。
Google Guavaの TreeMultiset クラスを使用します。 Guava には素晴らしいコレクションAPIがあります。
ソートされた順序を維持するListの実装を提供することの1つの問題は、add()
メソッドのJavaDocsで行われた約束です。
いくつかのオプションがあります。複製が不要で、挿入するオブジェクトが同等である場合は、TreeSetをお勧めします。
Collectionsクラスの静的メソッドを使用してこれを行うこともできます。
詳細については、 Collections#sort(Java.util.List) および TreeSet を参照してください。
リストを並べ替えるだけの場合は、あらゆる種類の List を使用し、 Collections.sort() を使用します。リスト内の要素が一意であり、常にソートされていることを確認する場合は、 SortedSet を使用します。
あなたが望むようにソートされたリストを実装する最も効率的な方法は、次のようにインデックス付け可能なスキップリストを実装することです: Wikipedia:Indexable skiplist 。 O(log(n))に挿入/削除を許可し、同時にインデックス付きアクセスを許可します。また、重複も許可します。
スキップリストは非常に興味深いものであり、過小評価されているデータ構造です。残念ながら、Javaベースライブラリにはインデックス付きスキップリスト実装はありませんが、オープンソース実装の1つを使用するか、自分で実装することができます。 ConcurrentSkipListSet や ConcurrentSkipListMap のような通常のスキップリスト実装があります
私がしたことは、すべてのメソッドが委任された内部インスタンスを持つListを実装することです。
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();
}
TreeSetは重複を許可せず、特定の位置で要素を取得するメソッドを提供しないため、動作しません。 PriorityQueueは、リストの基本的な要件である特定の位置で要素をフェッチできないため、機能しません。重複を必要としない限り、Java挿入時間でO(logn)のソート済みリストを維持するには、独自のアルゴリズムを実装する必要があると思います。たぶん、解決策は、キーがequalsメソッドをオーバーライドするアイテムのサブクラスであるTreeMapを使用して、重複が許可されるようにすることです。
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()));
PriorityQueueの問題は、単純な配列によってバックアップされていることと、要素を順番に取得するロジックが「queue [2 * n + 1] and queue [2 *(n + 1)]」によって行われることです。頭から引っ張るだけでうまく機能しますが、ある時点でその上で.toArrayを呼び出そうとすると役に立たなくなります。
Com.google.common.collect.TreeMultimapを使用してこの問題を回避しますが、値には、0を返さないOrderingでラップされたカスタムコンパレーターを提供します。
例ダブルの場合:
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()を呼び出すときに値を順番に取得しますが、重複もあります。
Setには、TreeSetを使用できます。 TreeSetは、自然な順序または特定のオブジェクトのComparableに渡された並べ替え順序に基づいて要素を順序付けます。マップにはTreeMapを使用します。 TreeMapはキーのソートを提供します。 TreeMapにキーとしてオブジェクトを追加するには、そのクラスは比較可能なインターフェイスを実装する必要があり、このインターフェイスは並べ替え順序の定義を含むcompare to()メソッドの実装を強制します。 http://techmastertutorial.in/Java-collection-impl.html
ArraylistとTreemapを使用できます。繰り返し値も必要だと言ったので、TreeSetは使用できませんが、並べ替えられますが、コンパレータを定義する必要があります。
必要なのは、バイナリ検索ツリーです。ソートされた順序を維持しながら、検索、削除、および挿入の対数アクセスを提供します(縮退したツリーがない場合-それは線形です)。実装は非常に簡単で、Listインターフェイスを実装することもできますが、インデックスアクセスは複雑になります。
2番目のアプローチは、ArrayListを使用してから、バブルソートを実装することです。一度に1つの要素を挿入または削除するため、挿入および削除のアクセス時間は直線的です。検索は対数およびインデックスアクセス定数です(LinkedListでは時間が異なる場合があります)。必要なコードは5、6行のバブルソートのみです。
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
import Java.util.TreeSet;
public class Ass3 {
TreeSet<String>str=new TreeSet<String>();
str.add("dog");
str.add("doonkey");
str.add("rat");
str.add("rabbit");
str.add("elephant");
System.out.println(str);
}
ユーザー定義の基準に従って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
TreeSet
を使用します。これは、ソートされた順序で要素を提供します。 OR Collection.sort()
を使用した外部ソートには、Comparator()
を使用します。
Java 8コンパレータを使用して、リストを並べ替える場合、ここに世界で最も人口の多い10の都市があり、Timeで報告されているように、名前で並べ替えます。大阪、日本。 ...メキシコシティ、メキシコ。 ... 中国、北京。 ...ブラジル、サンパウロ。 ...ムンバイ、インド。 ... 中国、上海。 ...インドのデリー。 ... 東京、日本。
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);
}
}