객체 배열이 있습니다 person (int age; String name;)
.
이 배열을 알파벳순으로 이름순으로 정렬 한 다음 어떻게 연령 순으로 정렬 할 수 있습니까?
어떤 알고리즘을 사용 하시겠습니까?
답변
Collections.sort
다음과 같이 사용할 수 있습니다 .
private static void order(List<Person> persons) {
Collections.sort(persons, new Comparator() {
public int compare(Object o1, Object o2) {
String x1 = ((Person) o1).getName();
String x2 = ((Person) o2).getName();
int sComp = x1.compareTo(x2);
if (sComp != 0) {
return sComp;
}
Integer x1 = ((Person) o1).getAge();
Integer x2 = ((Person) o2).getAge();
return x1.compareTo(x2);
}});
}
List<Persons>
이제 이름, 나이별로 정렬됩니다.
String.compareTo
” 문서 에서 두 개의 문자열을 사전 식으로 비교합니다 .”
Collections.sort
네이티브 콜렉션 라이브러리의 정적 메소드입니다. 실제 정렬을 수행하므로 목록의 두 요소를 비교하는 방법을 정의하는 Comparator를 제공하면 compare
됩니다.
답변
Java 8 스트리밍 API를 사용할 수있는 사람들을 위해 여기에 잘 정리 된 깔끔한 접근 방식이 있습니다 :
Lambdas 및 정렬
C # LINQ와 동등한 것을 찾고있었습니다.
.ThenBy(...)
비교기에서 Java 8의 메커니즘을 찾았습니다.
.thenComparing(...)
알고리즘을 보여주는 스 니펫은 다음과 같습니다.
Comparator<Person> comparator = Comparator.comparing(person -> person.name);
comparator = comparator.thenComparing(Comparator.comparing(person -> person.age));
더 깔끔한 방법과 위의 링크를 확인하여 Java의 형식 유추가 LINQ와 비교하여 정의하기가 조금 더 어색한 방법에 대한 설명을 확인하십시오.
참조를위한 전체 단위 테스트는 다음과 같습니다.
@Test
public void testChainedSorting()
{
// Create the collection of people:
ArrayList<Person> people = new ArrayList<>();
people.add(new Person("Dan", 4));
people.add(new Person("Andi", 2));
people.add(new Person("Bob", 42));
people.add(new Person("Debby", 3));
people.add(new Person("Bob", 72));
people.add(new Person("Barry", 20));
people.add(new Person("Cathy", 40));
people.add(new Person("Bob", 40));
people.add(new Person("Barry", 50));
// Define chained comparators:
// Great article explaining this and how to make it even neater:
// http://blog.jooq.org/2014/01/31/java-8-friday-goodies-lambdas-and-sorting/
Comparator<Person> comparator = Comparator.comparing(person -> person.name);
comparator = comparator.thenComparing(Comparator.comparing(person -> person.age));
// Sort the stream:
Stream<Person> personStream = people.stream().sorted(comparator);
// Make sure that the output is as expected:
List<Person> sortedPeople = personStream.collect(Collectors.toList());
Assert.assertEquals("Andi", sortedPeople.get(0).name); Assert.assertEquals(2, sortedPeople.get(0).age);
Assert.assertEquals("Barry", sortedPeople.get(1).name); Assert.assertEquals(20, sortedPeople.get(1).age);
Assert.assertEquals("Barry", sortedPeople.get(2).name); Assert.assertEquals(50, sortedPeople.get(2).age);
Assert.assertEquals("Bob", sortedPeople.get(3).name); Assert.assertEquals(40, sortedPeople.get(3).age);
Assert.assertEquals("Bob", sortedPeople.get(4).name); Assert.assertEquals(42, sortedPeople.get(4).age);
Assert.assertEquals("Bob", sortedPeople.get(5).name); Assert.assertEquals(72, sortedPeople.get(5).age);
Assert.assertEquals("Cathy", sortedPeople.get(6).name); Assert.assertEquals(40, sortedPeople.get(6).age);
Assert.assertEquals("Dan", sortedPeople.get(7).name); Assert.assertEquals(4, sortedPeople.get(7).age);
Assert.assertEquals("Debby", sortedPeople.get(8).name); Assert.assertEquals(3, sortedPeople.get(8).age);
// Andi : 2
// Barry : 20
// Barry : 50
// Bob : 40
// Bob : 42
// Bob : 72
// Cathy : 40
// Dan : 4
// Debby : 3
}
/**
* A person in our system.
*/
public static class Person
{
/**
* Creates a new person.
* @param name The name of the person.
* @param age The age of the person.
*/
public Person(String name, int age)
{
this.age = age;
this.name = name;
}
/**
* The name of the person.
*/
public String name;
/**
* The age of the person.
*/
public int age;
@Override
public String toString()
{
if (name == null) return super.toString();
else return String.format("%s : %d", this.name, this.age);
}
}
답변
Java 8 스트림 접근 방식 사용 …
//Creates and sorts a stream (does not sort the original list)
persons.stream().sorted(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
그리고 Java 8 Lambda 접근 방식은 …
//Sorts the original list Lambda style
persons.sort((p1, p2) -> {
if (p1.getName().compareTo(p2.getName()) == 0) {
return p1.getAge().compareTo(p2.getAge());
} else {
return p1.getName().compareTo(p2.getName());
}
});
마지막으로 …
//This is similar SYNTAX to the Streams above, but it sorts the original list!!
persons.sort(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
답변
당신은 당신 자신을 구현 Comparator
하고 그것을 사용해야합니다 : 예를 들어
Arrays.sort(persons, new PersonComparator());
비교기는 다음과 같이 보일 수 있습니다.
public class PersonComparator implements Comparator<? extends Person> {
public int compare(Person p1, Person p2) {
int nameCompare = p1.name.compareToIgnoreCase(p2.name);
if (nameCompare != 0) {
return nameCompare;
} else {
return Integer.valueOf(p1.age).compareTo(Integer.valueOf(p2.age));
}
}
}
비교기는 먼저 이름을 비교하고, 같지 않으면 비교 결과를 반환하고, 그렇지 않으면 두 사람의 나이를 비교할 때 비교 결과를 반환합니다.
이 코드는 초안 일뿐입니다. 클래스는 불변이기 때문에 단일 정렬을 만드는 대신 각 정렬에 대해 새 인스턴스를 만드는 것을 생각할 수 있습니다.
답변
이를 위해 Java 8 Lambda 접근 방식을 사용할 수 있습니다. 이처럼 :
persons.sort(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
답변
person 클래스가 Comparable<Person>
다음과 같이 compareTo 메소드를 구현 한 다음 구현하십시오.
public int compareTo(Person o) {
int result = name.compareToIgnoreCase(o.name);
if(result==0) {
return Integer.valueOf(age).compareTo(o.age);
}
else {
return result;
}
}
먼저 이름 (대소 문자 구분)으로 정렬 한 다음 나이별로 정렬합니다. 그런 다음 실행할 수 있습니다 Arrays.sort()
또는 Collections.sort()
사람 개체의 컬렉션 또는 배열에.
답변
구아바 ComparisonChain
는 깔끔한 방법을 제공합니다. 이 링크를 참조하십시오 .
체인 비교문을 수행하기위한 유틸리티입니다. 예를 들면 다음과 같습니다.
public int compareTo(Foo that) {
return ComparisonChain.start()
.compare(this.aString, that.aString)
.compare(this.anInt, that.anInt)
.compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
.result();
}