我有对象数组person (int age;字符串名称;)。
我如何按名字的字母顺序排序这个数组,然后按年龄?
你会用哪种算法呢?
我有对象数组person (int age;字符串名称;)。
我如何按名字的字母顺序排序这个数组,然后按年龄?
你会用哪种算法呢?
当前回答
使用Java 8 Streams方法,在getter上引用方法…
// Create a stream...
var sortedList = persons.stream()
// sort it (does not sort the original list)...
.sorted(Comparator.comparing(Person::getName)
.thenComparing(Person::getAge));
// and collect to a new list
.collect(Collectors.toList());
集合到数组ist也可以:
persons.stream()
.sorted(Comparator.comparing(Person::getName)
.thenComparing(Person::getAge));
.toArray(String[]::new);
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 syntax is similar to the Streams example above, but 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));
}
}
}
比较程序首先比较两个名字,如果它们不相等,就返回比较结果,否则就返回比较两人年龄时的比较结果。
这段代码只是一个草稿:因为这个类是不可变的,你可以考虑为它构建一个单例,而不是为每次排序创建一个新实例。
我不确定在Person类中写比较器是否丑陋。是这样的:
public class Person implements Comparable <Person> {
private String lastName;
private String firstName;
private int age;
public Person(String firstName, String lastName, int BirthDay) {
this.firstName = firstName;
this.lastName = lastName;
this.age = BirthDay;
}
public int getAge() {
return age;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
@Override
public int compareTo(Person o) {
// default compareTo
}
@Override
public String toString() {
return firstName + " " + lastName + " " + age + "";
}
public static class firstNameComperator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.firstName.compareTo(o2.firstName);
}
}
public static class lastNameComperator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.lastName.compareTo(o2.lastName);
}
}
public static class ageComperator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.age - o2.age;
}
}
}
public class Test {
private static void print() {
ArrayList<Person> list = new ArrayList();
list.add(new Person("Diana", "Agron", 31));
list.add(new Person("Kay", "Panabaker", 27));
list.add(new Person("Lucy", "Hale", 28));
list.add(new Person("Ashley", "Benson", 28));
list.add(new Person("Megan", "Park", 31));
list.add(new Person("Lucas", "Till", 27));
list.add(new Person("Nicholas", "Hoult", 28));
list.add(new Person("Aly", "Michalka", 28));
list.add(new Person("Adam", "Brody", 38));
list.add(new Person("Chris", "Pine", 37));
Collections.sort(list, new Person.lastNameComperator());
Iterator<Person> it = list.iterator();
while(it.hasNext())
System.out.println(it.next().toString());
}
}
当使用Guava的ComparisonChain时,我会很小心,因为它会为每个被比较的元素创建一个实例,所以如果你在排序,你会看到N x Log N个比较链的创建,或者如果你在迭代和检查相等,则会有N个实例。
如果可能的话,我会使用最新的Java 8 API或Guava的ordered API创建一个静态比较器,这里是Java 8的一个例子:
import java.util.Comparator;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.nullsLast;
private static final Comparator<Person> COMPARATOR = Comparator
.comparing(Person::getName, nullsLast(naturalOrder()))
.thenComparingInt(Person::getAge);
@Override
public int compareTo(@NotNull Person other) {
return COMPARATOR.compare(this, other);
}
以下是如何使用番石榴的订购API: https://github.com/google/guava/wiki/OrderingExplained
您可以使用集合。排序如下:
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>现在按姓名排序,然后按年龄排序。
compareto "按字典顺序比较两个字符串" -来自文档。
集合。sort是本地Collections库中的一个静态方法。它做实际的排序,你只需要提供一个Comparator来定义如何比较列表中的两个元素:这是通过提供你自己的compare方法实现来实现的。
或者,您可以利用Collections.sort()(或Arrays.sort())是稳定的(它不会对相等的元素重新排序)这一事实,并首先使用一个Comparator按年龄排序,然后使用另一个Comparator按名称排序。
在这种特定的情况下,这不是一个很好的主意,但如果你必须能够在运行时改变排序顺序,它可能是有用的。