답변:
이것은 매우 늦지 만 JDK에는 정렬 된 목록을 가질 목적으로 클래스가 있습니다. 이름이 (다른 Sorted*
인터페이스 와 순서가 맞지 않음) " java.util.PriorityQueue
"입니다. 을 Comparable<?>
사용 하거나을 사용하여 정렬 할 수 있습니다 Comparator
.
List
정렬 된 사용법 과의 차이점 Collections.sort(...)
은 힙 데이터 구조를 사용하여 O (log (n)) 삽입 성능을 사용하여 항상 부분 순서를 유지하지만 정렬 된 삽입은 ArrayList
O (n)입니다 (즉, 이진 검색 및 이동 사용).
그러나, 달리 List
, PriorityQueue
인덱스 액세스 (지원하지 않습니다 get(5)
), 한 번에 힙이 그들을 걸릴 것입니다에 항목에 액세스 할 수있는 유일한 방법은, 하나의 (따라서 이름을 PriorityQueue
).
TreeMap과 TreeSet은 내용을 정렬 된 순서로 반복합니다. 또는 ArrayList를 사용하고 Collections.sort ()를 사용하여 정렬 할 수 있습니다. 모든 클래스는 java.util에 있습니다.
자주 수정 하는 정렬 된 목록 을 유지 하려면 (즉, 정렬 외에도 중복을 허용하고 인덱스로 요소를 효율적으로 참조 할 수있는 구조), ArrayList를 사용하지만 요소를 삽입해야 할 때 지정된 요소를 추가 할 색인을 결정하려면 항상 Collections.binarySearch ()를 사용하십시오 . 후자의 방법은 목록을 정렬 된 순서로 유지하기 위해 삽입해야하는 색인을 알려줍니다.
Google Guava의 TreeMultiset 클래스를 사용하십시오 . 구아바 에는 화려한 컬렉션 API가 있습니다.
정렬 순서를 유지하는 List 구현을 제공하는 데있어 한 가지 문제점은 add()
메소드 의 JavaDoc에서 작성된 약속 입니다.
List
끝에 항상 추가 해야하는 요구 사항을 언급하면 +1입니다 .
당신은 원하는 SortedSet의의 구현, 즉 TreeSet의를 .
몇 가지 옵션이 있습니다. 중복을 원하지 않고 삽입하는 객체가 비슷한 경우 TreeSet을 제안합니다.
Collections 클래스의 정적 메소드를 사용하여이를 수행 할 수도 있습니다.
자세한 정보는 Collections # sort (java.util.List) 및 TreeSet 를 참조하십시오.
목록을 정렬하려면 모든 종류의 List 를 사용하고 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);
}
그 후, 요소가 존재하지 않거나 요소가 존재하는 경우를 대비하여 올바른 위치에 삽입하는 새로운 메소드 "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 메소드는 내부 목록을 수정할 수 있으므로주의해야합니다. 이 경우 내부 목록의 복사본을 반환하거나 예외를 다시 throw 할 수 있습니다.
public ListIterator<Contact> listIterator() {
return (new ArrayList<Contact>(list)).listIterator();
}
List
계약을 위반한다는 것 입니다. 어쩌면 구현하는 것이 낫습니다 Collection
. 만약 ContactList
정렬 한 후 contains()
사용하여 구현할 수 있습니다 binarySearch
더 효율적으로뿐만 아니라.
원하는 정렬 목록을 구현하는 가장 효율적인 방법은 Wikipedia : Indexable skiplist 와 같이 인덱싱 가능한 스킵 목록을 구현하는 것 입니다. O (log (n))에 삽입 / 제거를 허용하고 동시에 인덱스 액세스를 허용합니다. 또한 중복을 허용합니다.
스킵리스트는 꽤 흥미롭고 저평가 된 데이터 구조입니다. 불행히도 Java 기본 라이브러리에는 인덱싱 된 건너 뛰기 목록이 없지만 오픈 소스 구현 중 하나를 사용하거나 직접 구현할 수 있습니다. ConcurrentSkipListSet 및 ConcurrentSkipListMap 과 같은 일반적인 Skiplist 구현이 있습니다.
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 인터페이스를 구현할 수도 있지만 인덱스 액세스가 복잡해집니다.
두 번째 방법은 ArrayList와 버블 정렬 구현을 갖는 것입니다. 한 번에 하나의 요소를 삽입하거나 제거하기 때문에 삽입 및 제거에 대한 액세스 시간은 선형입니다. 검색은 로그 및 인덱스 액세스 상수입니다 (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
정렬 된 순서로 요소를 제공합니다. 또는을 사용 Collection.sort()
하여 외부 정렬에 사용하십시오 Comparator()
.
Java 8 Comparator를 사용하여 목록을 정렬하려면 세계에서 가장 인구가 많은 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