서로 다른 타이밍에 서로 다른 파라미터별로 목록을 정렬하려면 어떻게 해야 합니까?
라는 이름의 수업이 있습니다.Person
다음과 같은 여러 속성이 있습니다.
public class Person {
private int id;
private String name, address;
// Many more properties.
}
많은.Person
-syslogs는 에 저장됩니다.ArrayList<Person>
이 목록을 여러 개의 정렬 매개 변수를 기준으로 정렬하고 시간에 따라 다르게 정렬합니다.예를 들어, 한 번쯤은 다음 기준으로 정렬하고 싶을 수 있습니다.name
오름차순address
내리막길, 그리고 다음에 그냥 지나칠 때id
내림차순의
또한 나만의 정렬 방법을 만들고 싶지 않습니다(즉,Collections.sort(personList, someComparator)
이를 실현하는 가장 우아한 솔루션은 무엇입니까?
열거형 접근법은 기본적으로 타당하다고 생각합니다만, 스위치 문장은 좀 더 객체 지향적인 접근법이 필요합니다.고려사항:
enum PersonComparator implements Comparator<Person> {
ID_SORT {
public int compare(Person o1, Person o2) {
return Integer.valueOf(o1.getId()).compareTo(o2.getId());
}},
NAME_SORT {
public int compare(Person o1, Person o2) {
return o1.getFullName().compareTo(o2.getFullName());
}};
public static Comparator<Person> decending(final Comparator<Person> other) {
return new Comparator<Person>() {
public int compare(Person o1, Person o2) {
return -1 * other.compare(o1, o2);
}
};
}
public static Comparator<Person> getComparator(final PersonComparator... multipleOptions) {
return new Comparator<Person>() {
public int compare(Person o1, Person o2) {
for (PersonComparator option : multipleOptions) {
int result = option.compare(o1, o2);
if (result != 0) {
return result;
}
}
return 0;
}
};
}
}
(스태틱 Import에서의) 사용 예.
public static void main(String[] args) {
List<Person> list = null;
Collections.sort(list, decending(getComparator(NAME_SORT, ID_SORT)));
}
정렬할 각 속성에 대해 비교기를 만든 다음 다음과 같이 "comparator chaining" :-)을 시도할 수 있습니다.
public class ChainedComparator<T> implements Comparator<T> {
private List<Comparator<T>> simpleComparators;
public ChainedComparator(Comparator<T>... simpleComparators) {
this.simpleComparators = Arrays.asList(simpleComparators);
}
public int compare(T o1, T o2) {
for (Comparator<T> comparator : simpleComparators) {
int result = comparator.compare(o1, o2);
if (result != 0) {
return result;
}
}
return 0;
}
}
한 가지 방법은 다음과 같습니다.Comparator
다음 예시와 같이 정렬할 속성 목록을 인수로 사용합니다.
public class Person {
private int id;
private String name, address;
public static Comparator<Person> getComparator(SortParameter... sortParameters) {
return new PersonComparator(sortParameters);
}
public enum SortParameter {
ID_ASCENDING, ID_DESCENDING, NAME_ASCENDING,
NAME_DESCENDING, ADDRESS_ASCENDING, ADDRESS_DESCENDING
}
private static class PersonComparator implements Comparator<Person> {
private SortParameter[] parameters;
private PersonComparator(SortParameter[] parameters) {
this.parameters = parameters;
}
public int compare(Person o1, Person o2) {
int comparison;
for (SortParameter parameter : parameters) {
switch (parameter) {
case ID_ASCENDING:
comparison = o1.id - o2.id;
if (comparison != 0) return comparison;
break;
case ID_DESCENDING:
comparison = o2.id - o1.id;
if (comparison != 0) return comparison;
break;
case NAME_ASCENDING:
comparison = o1.name.compareTo(o2.name);
if (comparison != 0) return comparison;
break;
case NAME_DESCENDING:
comparison = o2.name.compareTo(o1.name);
if (comparison != 0) return comparison;
break;
case ADDRESS_ASCENDING:
comparison = o1.address.compareTo(o2.address);
if (comparison != 0) return comparison;
break;
case ADDRESS_DESCENDING:
comparison = o2.address.compareTo(o1.address);
if (comparison != 0) return comparison;
break;
}
}
return 0;
}
}
}
그런 다음 다음과 같은 코드로 사용할 수 있습니다.
cp = Person.getComparator(Person.SortParameter.ADDRESS_ASCENDING,
Person.SortParameter.NAME_DESCENDING);
Collections.sort(personList, cp);
한 가지 접근법은 작곡하는 것입니다.Comparator
s. 이것은 라이브러리 방법일 수 있습니다(확실히 어딘가에 존재합니다).
public static <T> Comparator<T> compose(
final Comparator<? super T> primary,
final Comparator<? super T> secondary
) {
return new Comparator<T>() {
public int compare(T a, T b) {
int result = primary.compare(a, b);
return result==0 ? secondary.compare(a, b) : result;
}
[...]
};
}
용도:
Collections.sort(people, compose(nameComparator, addressComparator));
또는 다음 점에 주의해 주십시오.Collections.sort
안정적인 종류입니다.성능이 절대적으로 중요하지 않은 경우에는 프라이머리보다 먼저 정렬합니다.
Collections.sort(people, addressComparator);
Collections.sort(people, nameComparator);
비교기를 사용하면 매우 쉽고 자연스럽게 이 작업을 수행할 수 있습니다.개인 클래스 자체 또는 필요에 따라 연결된 서비스 클래스에 비교기의 단일 인스턴스를 만들 수 있습니다.
예: 익명 내부 클래스 사용:
public static final Comparator<Person> NAME_ASC_ADRESS_DESC
= new Comparator<Person>() {
public int compare(Person p1, Person p2) {
int nameOrder = p1.getName().compareTo(p2.getName);
if(nameOrder != 0) {
return nameOrder;
}
return -1 * p1.getAdress().comparedTo(p2.getAdress());
// I use explicit -1 to be clear that the order is reversed
}
};
public static final Comparator<Person> ID_DESC
= new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return -1 * p1.getId().comparedTo(p2.getId());
// I use explicit -1 to be clear that the order is reversed
}
};
// and other comparator instances as needed...
많은 경우 원하는 방식으로 대조군 코드를 구성할 수도 있습니다.예를 들어 다음과 같습니다.
- 다른 대조군으로부터 상속받습니다.
- 일부 기존 대조군을 조정하는 Composite Comparator가 있다
- NullComparator를 사용하여 NullComparator를 처리한 후 다른 Comparator에 위임합니다.
- 기타...
당신의 답변에서와 같이 분류기를 Person 클래스에 결합하는 것은 좋은 생각이 아니라고 생각합니다.왜냐하면 비교(통상 비즈니스 중심)와 모델 오브젝트를 서로 가깝게 결합하기 때문입니다.정렬기를 변경하거나 추가할 때마다 사용자 클래스를 터치해야 합니다. 이는 보통 원하지 않는 작업입니다.
KLE이 제안하는 것과 같은 Comparator 인스턴스를 제공하는 서비스 또는 이와 유사한 서비스를 사용하는 것이 훨씬 유연하고 확장성이 높은 것으로 보입니다.
나의 접근법은 Yishai를 기반으로 한다.가장 큰 차이는 애트리뷰트에 대해 처음에 오름차순 정렬을 한 후 다른 애트리뷰트에 대해 오름차순 정렬을 할 방법이 없다는 것입니다.이 작업은 열거형으로는 수행할 수 없습니다.그러기 위해 나는 수업을 이용했다.SortOrder는 내부 클래스로 구현하기 위해 선호하는 유형에 따라 크게 달라지기 때문입니다.
내부 클래스 'SortOrder'가 있는 클래스 'Person'은 다음과 같습니다.
import java.util.Comparator;
public class Person {
private int id;
private String firstName;
private String secondName;
public Person(int id, String firstName, String secondName) {
this.id = id;
this.firstName = firstName;
this.secondName = secondName;
}
public abstract static class SortOrder implements Comparator<Person> {
public static SortOrder PERSON_ID = new SortOrder() {
public int compare(Person p1, Person p2) {
return Integer.valueOf(p1.getId()).compareTo(p2.getId());
}
};
public static SortOrder PERSON_FIRST_NAME = new SortOrder() {
public int compare(Person p1, Person p2) {
return p1.getFirstName().compareTo(p2.getFirstName());
}
};
public static SortOrder PERSON_SECOND_NAME = new SortOrder() {
public int compare(Person p1, Person p2) {
return p1.getSecondName().compareTo(p2.getSecondName());
}
};
public static SortOrder invertOrder(final SortOrder toInvert) {
return new SortOrder() {
public int compare(Person p1, Person p2) {
return -1 * toInvert.compare(p1, p2);
}
};
}
public static Comparator<Person> combineSortOrders(final SortOrder... multipleSortOrders) {
return new Comparator<Person>() {
public int compare(Person p1, Person p2) {
for (SortOrder personComparator: multipleSortOrders) {
int result = personComparator.compare(p1, p2);
if (result != 0) {
return result;
}
}
return 0;
}
};
}
}
public int getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getSecondName() {
return secondName;
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append("Person with id: ");
result.append(id);
result.append(" and firstName: ");
result.append(firstName);
result.append(" and secondName: ");
result.append(secondName);
result.append(".");
return result.toString();
}
}
클래스와 해당 SortOrder를 사용하는 예:
import static multiplesortorder.Person.SortOrder.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import multiplesortorder.Person;
public class Application {
public static void main(String[] args) {
List<Person> listPersons = new ArrayList<Person>(Arrays.asList(
new Person(0, "...", "..."),
new Person(1, "...", "...")
));
Collections.sort(listPersons, combineSortOrders(PERSON_FIRST_NAME, invertOrder(PERSON_ID)));
for (Person p: listPersons) {
System.out.println(p.toString());
}
}
}
오루모
최근에 구분된 String 레코드 내의 여러 필드를 정렬하는 Comparator를 작성했습니다.딜리미터, 레코드 구조 및 정렬 규칙(일부 유형은 고유)을 정의할 수 있습니다.사용자 레코드를 구분 문자열로 변환하여 사용할 수 있습니다.
필요한 정보는 프로그래밍 방식으로 또는 XML 파일을 통해 Comparator 자체에 시드됩니다.
XML은 패키지 포함 XSD 파일에 의해 검증됩니다.예를 들어, 4개의 필드(이 중 2개는 정렬 가능)가 있는 탭으로 구분된 레코드 레이아웃을 다음에 나타냅니다.
<?xml version="1.0" encoding="ISO-8859-1"?>
<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<delimiter>	</delimiter>
<column xsi:type="Decimal">
<name>Column One</name>
</column>
<column xsi:type="Integer">
<name>Column Two</name>
</column>
<column xsi:type="String">
<name>Column Three</name>
<sortOrder>2</sortOrder>
<trim>true</trim>
<caseSensitive>false</caseSensitive>
<stripAccents>true</stripAccents>
</column>
<column xsi:type="DateTime">
<name>Column Four</name>
<sortOrder>1</sortOrder>
<ascending>true</ascending>
<nullLowSortOrder>true</nullLowSortOrder>
<trim>true</trim>
<pattern>yyyy-MM-dd</pattern>
</column>
</row>
그런 다음 Java에서 다음과 같이 사용합니다.
Comparator<String> comparator = new RowComparator(
new XMLStructureReader(new File("layout.xml")));
라이브러리는 다음 사이트에서 찾을 수 있습니다.
http://sourceforge.net/projects/multicolumnrowcomparator/
를 들어, 어떤 클래스가 있다고 가정합니다.Coordinate
X좌표와 Y좌표에 따라 두 가지 방법으로 정렬해야 합니다.여기에는 2개의 다른 비교기가 필요합니다.입니다.
class Coordinate
{
int x,y;
public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
static Comparator<Coordinate> getCoordinateXComparator() {
return new Comparator<Coordinate>() {
@Override
public int compare(Coordinate Coordinate1, Coordinate Coordinate2) {
if(Coordinate1.x < Coordinate2.x)
return 1;
else
return 0;
}
// compare using Coordinate x
};
}
static Comparator<Coordinate> getCoordinateYComparator() {
return new Comparator<Coordinate>() {
@Override
public int compare(Coordinate Coordinate1, Coordinate Coordinate2) {
if(Coordinate1.y < Coordinate2.y)
return 1;
else
return 0;
}
// compare using Coordinate y
};
}
}
언급URL : https://stackoverflow.com/questions/1421322/how-do-i-sort-a-list-by-different-parameters-at-different-timed
'programing' 카테고리의 다른 글
Django가 있는 AngularJS - 템플릿 태그가 충돌합니다. (0) | 2022.11.24 |
---|---|
Vue.js - 키와 값을 사용하여 객체를 객체 배열로 변환 (0) | 2022.11.24 |
한 데이터베이스에서 포함된 테이블을 복사하고 다른 데이터베이스 테이블에 삽입하려고 합니다. (0) | 2022.11.24 |
MySQL "NOT IN" 쿼리 (0) | 2022.11.24 |
Vuetify로 달력 보기 구성 요소에서 본문 제목 월 및 연도 요소를 제거합니다. (0) | 2022.11.24 |