Відповіді:
Це відбувається дуже пізно, але в JDK є клас лише для того, щоб мати відсортований список. Він названий (дещо не в порядку з іншими Sorted*
інтерфейсами) " java.util.PriorityQueue
". Він може сортувати або Comparable<?>
s, або використовуючи Comparator
.
Відмінність List
відсортованого використання Collections.sort(...)
полягає в тому, що це підтримуватиме частковий порядок у будь-який час, з продуктивністю вставки O (log (n)), використовуючи структуру даних купи, тоді як впорядкована вставка ArrayList
буде O (n) (тобто за допомогою двійкового пошуку та переміщення).
Однак, на відміну від a List
, PriorityQueue
не підтримує індексований доступ ( get(5)
), єдиний спосіб доступу до елементів у купі - це виймати їх по одному (таким чином, назва PriorityQueue
).
TreeMap і TreeSet нададуть вам ітерацію вмісту в упорядкованому порядку. Або ви можете використовувати ArrayList і використовувати Collections.sort () для сортування. Усі ці заняття в java.util
Якщо ви хочете підтримувати відсортований список, який ви будете часто змінювати (тобто структуру, яка, крім сортування, дозволяє копії та елементи, на які можна ефективно посилатись за індексом), тоді використовуйте ArrayList, але коли вам потрібно вставити елемент , завжди використовуйте Collections.binarySearch (), щоб визначити індекс, до якого ви додаєте заданий елемент. Останній метод повідомляє вам індекс, який потрібно вставити, щоб зберегти список у відсортованому порядку.
Використовуйте клас TreeMultiset Google Guava . У Guava є ефектна колекція API.
Однією із проблем із забезпеченням реалізації списку, який підтримує відсортований порядок, є обіцянки, зроблені в JavaDocs add()
методу.
List
завжди додається в кінці.
Є кілька варіантів. Я б запропонував TreeSet, якщо ви не хочете копій, а об'єкти, які ви вставляєте, порівнянні.
Для цього також можна використовувати статичні методи класу Collections.
Додаткову інформацію див. У колекціях # sort (java.util.List) та TreeSet .
Якщо ви просто хочете сортувати список, використовуйте будь-який тип списку та використовуйте Collections.sort () . Якщо ви хочете, щоб елементи у списку були унікальними та завжди відсортованими, використовуйте SortedSet .
Що я зробив, це реалізувати 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);
}
Після цього я реалізував новий метод "putOrряд", який вставляють у правильне положення, якщо елемент не існує або заміняється на всякий випадок, якщо він існує.
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);
}
}
Якщо ви хочете дозволити повторювані елементи, просто застосуйте addOrряд замість (або обидва).
public void addOrdered(Contact contact) {
int index=Collections.binarySearch(this.list,contact);
if(index<0){
index= -(index+1);
}
list.add(index, contact);
}
Якщо ви хочете уникнути вставок, ви можете також викидати і непідтримувані винятки операцій методами "додати" та "встановити".
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
і з використанням більш ефективної.
Найефективнішим способом реалізації відсортованого списку, як ви хочете, було б застосувати індексируваний пропускний список, як тут: Вікіпедія: Індекс, що індексується . Це дозволило б мати вставки / видалення в O (log (n)) і дозволило б одночасно мати індексований доступ. І це також дозволило б дублікати.
Skiplist - це досить цікава і, я б сказав, недооцінена структура даних. На жаль, в базовій бібліотеці Java немає індексованої реалізації пропускних списків, але ви можете використовувати одну з реалізацій з відкритим кодом або реалізувати її самостійно. Є регулярні реалізації Skiplist, такі як ConcurrentSkipListSet та ConcurrentSkipListMap
TreeSet не працює, тому що вони не дозволяють дублікати плюс вони не надають метод для отримання елемента в певній позиції. PriorityQueue не працюватиме, оскільки не дозволяє отримати елементи в певній позиції, що є основною вимогою для списку. Я думаю, що вам потрібно реалізувати власний алгоритм для підтримки відсортованого списку в Java з вкладеним часом O (logn), якщо вам не потрібні дублікати. Можливо, рішенням може бути використання TreeMap, де ключ є підкласом елемента, що переосмислює метод рівних, так що дублікати дозволені.
Ви можете спробувати вирішити ці завдання з LambdaJ, якщо ви використовуєте попередні версії до java 8. Ви можете знайти їх тут: 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] and queue [2 * (n + 1)]" thingie. Це чудово працює, якщо ви просто тягнете з голови, але робить його марним, якщо ви намагаєтесь в якийсь момент викликати .toArray на ньому.
Я подолаю цю проблему, використовуючи com.google.common.collect.TreeMultimap, але надаю користувальницький компаратор для значень, загорнутих у замовлення, який ніколи не повертає 0.
колишній для 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;
}
}
});
Таким чином я отримую значення в порядку, коли я викликаю .toArray (), а також маю дублікати.
Що ви хочете - це двійкове дерево пошуку. Він підтримує відсортований порядок, пропонуючи логарифмічний доступ для пошуку, видалення та вставки (якщо у вас не вироджене дерево - тоді це лінійно). Це досить просто реалізувати, і ви навіть можете змусити його реалізувати інтерфейс List, але тоді доступ до індексу ускладнюється.
Другий підхід - це створення ArrayList, а потім реалізація сортування бульбашок. Оскільки ви вставляєте або видаляєте один за одним, час доступу для вставок та видалень лінійний. Пошуки є логарифмічними та постійними доступом до індексу (час може бути різним для LinkedList). Єдиний код, який вам потрібен, це 5, можливо 6 рядків сортування міхура.
Ви можете використовувати Arraylist і Treemap, як ви сказали, що також потрібно повторювати значення, тоді ви не можете використовувати TreeSet, хоча він також відсортований, але ви повинні визначити компаратор.
Для Set ви можете використовувати TreeSet. TreeSet замовляє його елементи на основі природного впорядкування або будь-якого порядку сортування, переданого на Порівняльний для цього конкретного об'єкта. Для карти використовуйте TreeMap. TreeMap забезпечує сортування клавіш. Щоб додати об’єкт як ключ до TreeMap, цей клас повинен реалізувати порівнянний інтерфейс, який, у свою чергу, змушує реалізувати метод порівняння з (), який містить визначення порядку сортування. 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
що дає елементи в упорядкованому порядку. АБО використовувати Collection.sort()
для зовнішнього сортування за допомогою 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);
}
за допомогою порівняльника 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);
}
}
Сортування 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