Antworten:
Dies kommt sehr spät, aber es gibt eine Klasse im JDK, nur um eine sortierte Liste zu haben. Es heißt (etwas außer Betrieb mit den anderen Sorted*
Schnittstellen) " java.util.PriorityQueue
". Es kann entweder Comparable<?>
s oder mit a sortieren Comparator
.
Der Unterschied zu einer List
sortierten Verwendung Collections.sort(...)
besteht darin, dass durch die Verwendung einer Heap-Datenstruktur ArrayList
jederzeit eine Teilreihenfolge mit einer Einfügungsleistung von O (log (n)) beibehalten wird, während die Einfügung in eine sortierte Reihenfolge O (n) ist (dh mit binärer Suche und Bewegung).
Doch im Gegensatz zu einem List
, PriorityQueue
bietet keine Unterstützung für den indizierten Zugriff ( get(5)
), die einzige Möglichkeit , den Zugriff auf Elemente in einem Haufen sie aus, einer nach dem anderen zu nehmen ist (daher der Name PriorityQueue
).
TreeMap und TreeSet geben Ihnen eine Iteration über den Inhalt in sortierter Reihenfolge. Oder Sie können eine ArrayList verwenden und Collections.sort () verwenden, um sie zu sortieren. Alle diese Klassen befinden sich in java.util
Wenn Sie eine sortierte Liste pflegen möchten, die Sie häufig ändern (dh eine Struktur, die nicht nur sortiert ist, sondern auch Duplikate zulässt und deren Elemente effizient durch den Index referenziert werden können), verwenden Sie eine ArrayList, wenn Sie jedoch ein Element einfügen müssen Verwenden Sie immer Collections.binarySearch (), um den Index zu bestimmen, an dem Sie ein bestimmtes Element hinzufügen. Die letztere Methode gibt an, bei welchem Index Sie einfügen müssen, um Ihre Liste in sortierter Reihenfolge zu halten.
Verwenden Sie die TreeMultiset- Klasse von Google Guava . Guave hat eine spektakuläre Sammlungs-API.
Ein Problem bei der Bereitstellung einer Implementierung von List, die die sortierte Reihenfolge beibehält, ist das in den JavaDocs der add()
Methode gemachte Versprechen .
List
immer am Ende hinzugefügt wird.
Sie möchten die SortedSet- Implementierungen, nämlich TreeSet .
Es gibt einige Optionen. Ich würde TreeSet vorschlagen, wenn Sie keine Duplikate möchten und die Objekte, die Sie einfügen, vergleichbar sind.
Sie können dazu auch die statischen Methoden der Collections-Klasse verwenden.
Weitere Informationen finden Sie unter Sammlungen # sort (java.util.List) und TreeSet .
Wenn Sie nur eine Liste sortieren möchten, verwenden Sie eine beliebige Liste und verwenden Sie Collections.sort () . Wenn Sie sicherstellen möchten, dass die Elemente in der Liste eindeutig und immer sortiert sind, verwenden Sie ein SortedSet .
Was ich getan habe, ist die Implementierung von List mit einer internen Instanz mit allen delegierten Methoden.
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);
}
Danach habe ich eine neue Methode "putOrdered" implementiert, die an der richtigen Position einfügt, wenn das Element nicht existiert, oder ersetzt, nur für den Fall, dass es existiert.
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);
}
}
Wenn Sie wiederholte Elemente zulassen möchten, implementieren Sie stattdessen addOrdered (oder beides).
public void addOrdered(Contact contact) {
int index=Collections.binarySearch(this.list,contact);
if(index<0){
index= -(index+1);
}
list.add(index, contact);
}
Wenn Sie Einfügungen vermeiden möchten, können Sie auch eine Ausnahme für nicht unterstützte Operationen für die Methoden "add" und "set" auslösen.
public boolean add(Contact object) {
throw new UnsupportedOperationException("Use putOrdered instead");
}
... und Sie müssen auch mit ListIterator-Methoden vorsichtig sein, da diese Ihre interne Liste ändern können. In diesem Fall können Sie eine Kopie der internen Liste zurückgeben oder erneut eine Ausnahme auslösen.
public ListIterator<Contact> listIterator() {
return (new ArrayList<Contact>(list)).listIterator();
}
List
Vertrag verstößt . Vielleicht wäre es besser, nur zu implementieren Collection
. Und wenn ContactList
es sortiert ist, contains()
kann es auch implementiert werden binarySearch
, um effizienter zu sein.
Der effizienteste Weg, eine sortierte Liste wie gewünscht zu implementieren, besteht darin, eine indizierbare Skiplist wie hier zu implementieren: Wikipedia: Indexable Skiplist . Es würde Einfügungen / Entfernungen in O (log (n)) ermöglichen und gleichzeitig einen indizierten Zugriff ermöglichen. Und es würde auch Duplikate erlauben.
Skiplist ist eine ziemlich interessante und, ich würde sagen, unterschätzte Datenstruktur. Leider gibt es in der Java-Basisbibliothek keine indizierte Skiplist-Implementierung, aber Sie können eine der Open Source-Implementierungen verwenden oder selbst implementieren. Es gibt regelmäßige Skiplist-Implementierungen wie ConcurrentSkipListSet und ConcurrentSkipListMap
TreeSet würde nicht funktionieren, da sie keine Duplikate zulassen und keine Methode zum Abrufen von Elementen an einer bestimmten Position bereitstellen. PriorityQueue würde nicht funktionieren, da es nicht möglich ist, Elemente an einer bestimmten Position abzurufen, was eine Grundvoraussetzung für eine Liste ist. Ich denke, Sie müssen Ihren eigenen Algorithmus implementieren, um eine sortierte Liste in Java mit O (logn) Einfügezeit zu verwalten, es sei denn, Sie benötigen keine Duplikate. Möglicherweise könnte eine Lösung die Verwendung einer TreeMap sein, bei der der Schlüssel eine Unterklasse des Elements ist, das die Methode equals überschreibt, sodass Duplikate zulässig sind.
Sie können versuchen, diese Aufgaben mit LambdaJ zu lösen, wenn Sie frühere Versionen von Java 8 verwenden. Sie finden sie hier: http://code.google.com/p/lambdaj/
Hier haben Sie ein Beispiel:
Iterativ sortieren
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());
}
});
Sortieren mit LambdaJ
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());
Natürlich wirkt sich diese Art von Schönheit auf die Leistung aus (durchschnittlich zweimal), aber können Sie einen besser lesbaren Code finden?
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()))
Das Problem mit PriorityQueue besteht darin, dass es durch ein einfaches Array gesichert wird und die Logik, mit der die Elemente in der richtigen Reihenfolge abgerufen werden, vom Ding "Warteschlange [2 * n + 1] und Warteschlange [2 * (n + 1)]" ausgeführt wird. Es funktioniert gut, wenn Sie nur vom Kopf ziehen, macht es aber nutzlos, wenn Sie versuchen, das .toArray irgendwann darauf aufzurufen.
Ich gehe dieses Problem mit com.google.common.collect.TreeMultimap um, aber ich stelle einen benutzerdefinierten Komparator für die Werte bereit, die in eine Bestellung eingeschlossen sind und niemals 0 zurückgeben.
Ex. für Double:
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;
}
}
});
Auf diese Weise erhalte ich die Werte in der richtigen Reihenfolge, wenn ich .toArray () aufrufe, und habe auch Duplikate.
Was Sie wollen, ist ein binärer Suchbaum. Es behält die sortierte Reihenfolge bei und bietet gleichzeitig logarithmischen Zugriff für Suchen, Entfernen und Einfügen (es sei denn, Sie haben einen entarteten Baum - dann ist es linear). Es ist recht einfach zu implementieren und Sie können sogar die List-Schnittstelle implementieren lassen, aber dann wird der Indexzugriff kompliziert.
Der zweite Ansatz besteht darin, eine ArrayList und dann eine Implementierung für die Blasensortierung zu haben. Da Sie jeweils ein Element einfügen oder entfernen, sind die Zugriffszeiten für das Einfügen und Entfernen linear. Die Suche ist logarithmisch und die Indexzugriffskonstante (die Zeiten für LinkedList können unterschiedlich sein). Der einzige Code, den Sie benötigen, ist 5, vielleicht 6 Zeilen Blasensortierung.
Sie können Arraylist und Treemap verwenden, da Sie sagten, Sie möchten auch wiederholte Werte, dann können Sie TreeSet nicht verwenden, obwohl es ebenfalls sortiert ist, aber Sie müssen den Komparator definieren.
Für Set können Sie TreeSet verwenden. TreeSet ordnet seine Elemente auf der Grundlage einer natürlichen Reihenfolge oder einer Sortierreihenfolge an, die für dieses bestimmte Objekt an Comparable übergeben wird. Verwenden Sie für die Karte TreeMap. TreeMap bietet die Sortierung über Schlüssel. Um der TreeMap ein Objekt als Schlüssel hinzuzufügen, sollte diese Klasse eine vergleichbare Schnittstelle implementieren, die wiederum die Implementierung der Methode compare to () erzwingt, die die Definition der Sortierreihenfolge enthält. http://techmastertutorial.in/java-collection-impl.html
Verwenden Sie die Methode sort (), um die Liste wie folgt zu sortieren:
List list = new ArrayList();
//add elements to the list
Comparator comparator = new SomeComparator();
Collections.sort(list, comparator);
Referenz finden Sie unter folgendem Link: http://tutorials.jenkov.com/java-collections/sorting.html
Verwenden Sie TreeSet
diese Option, um Elemente in sortierter Reihenfolge anzugeben. ODER Collection.sort()
zur externen Sortierung mit verwenden Comparator()
.
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);
}
Wenn wir mit Java 8 Comparator die Liste sortieren möchten, dann sind hier die 10 bevölkerungsreichsten Städte der Welt, und wir möchten sie nach Namen sortieren, wie von Time angegeben. Osaka, Japan. ... Mexiko-Stadt, Mexiko. ... Peking, China. ... Sao Paulo, Brasilien. ... Mumbai, Indien. ... Shanghai, China. ... Delhi, Indien. ... Tokyo, Japan.
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);
}
}
Sortieren einer ArrayList nach benutzerdefinierten Kriterien.
Modellklasse
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;
}
}
Klasse sortieren
class Sortbyroll implements Comparator<Student>
{
public int compare(Student a, Student b)
{
return a.rollno - b.rollno;
}
}
Hauptklasse
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));
}
}
Ausgabe
Unsorted
111 bbbb london
131 aaaa nyc
121 cccc jaipur
Sorted by rollno
111 bbbb london
121 cccc jaipur
131 aaaa nyc