我会小心使用Guava ComparisonChain 因为它会为每个被比较的元素创建一个示例,所以您将看到 N x Log N 比较链只是为了在排序时进行比较,或者 N 如果您正在迭代并检查相等性,则返回一个示例。 我会创建一个静态 Comparator 尽可能使用最新的Java8API或guava的 Ordering 允许您这样做的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);
}
package books;
public class Book {
private Integer id;
private Integer number;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "book{" +
"id=" + id +
", number=" + number +
", name='" + name + '\'' + '\n' +
'}';
}
}
用模拟对象排序主类
package books;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
Book b = new Book();
Book c = new Book();
Book d = new Book();
Book e = new Book();
Book f = new Book();
Book g = new Book();
Book g1 = new Book();
Book g2 = new Book();
Book g3 = new Book();
Book g4 = new Book();
b.setId(1);
b.setNumber(12);
b.setName("gk");
c.setId(2);
c.setNumber(12);
c.setName("gk");
d.setId(2);
d.setNumber(13);
d.setName("maths");
e.setId(3);
e.setNumber(3);
e.setName("geometry");
f.setId(3);
f.setNumber(34);
b.setName("gk");
g.setId(3);
g.setNumber(11);
g.setName("gk");
g1.setId(3);
g1.setNumber(88);
g1.setName("gk");
g2.setId(3);
g2.setNumber(91);
g2.setName("gk");
g3.setId(3);
g3.setNumber(101);
g3.setName("gk");
g4.setId(3);
g4.setNumber(4);
g4.setName("gk");
List<Book> allBooks = new ArrayList<Book>();
allBooks.add(b);
allBooks.add(c);
allBooks.add(d);
allBooks.add(e);
allBooks.add(f);
allBooks.add(g);
allBooks.add(g1);
allBooks.add(g2);
allBooks.add(g3);
allBooks.add(g4);
System.out.println(allBooks.size());
Collections.sort(allBooks, new Comparator<Book>() {
@Override
public int compare(Book t, Book t1) {
int a = t.getId()- t1.getId();
if(a == 0){
int a1 = t.getNumber() - t1.getNumber();
return a1;
}
else
return a;
}
});
System.out.println(allBooks);
}
}
public int compareTo(Person o) {
int result = name.compareToIgnoreCase(o.name);
if(result==0) {
return Integer.valueOf(age).compareTo(o.age);
}
else {
return result;
}
}
//Sort by first and last name
System.out.println("\n2.Sort list of person objects by firstName then "
+ "by lastName then by age");
Comparator<Person> sortByFirstName
= (p, o) -> p.firstName.compareToIgnoreCase(o.firstName);
Comparator<Person> sortByLastName
= (p, o) -> p.lastName.compareToIgnoreCase(o.lastName);
Comparator<Person> sortByAge
= (p, o) -> Integer.compare(p.age,o.age);
//Sort by first Name then Sort by last name then sort by age
personList.stream().sorted(
sortByFirstName
.thenComparing(sortByLastName)
.thenComparing(sortByAge)
).forEach(person->
System.out.println(person));
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));
}
}
}
@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);
}
}
//Creates and sorts a stream (does not sort the original list)
persons.stream().sorted(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
Java8Lambda方法。。。
//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));
Arrays.sort(persons, new PersonComparator());
import java.util.Comparator;
public class PersonComparator implements Comparator<? extends Person> {
@Override
public int compare(Person o1, Person o2) {
if(null == o1 || null == o2 || null == o1.getName() || null== o2.getName() ){
throw new NullPointerException();
}else{
int nameComparisonResult = o1.getName().compareTo(o2.getName());
if(0 == nameComparisonResult){
return o1.getAge()-o2.getAge();
}else{
return nameComparisonResult;
}
}
}
}
class Person{
int age; String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
更新版本:
public class PersonComparator implements Comparator<? extends Person> {
@Override
public int compare(Person o1, Person o2) {
int nameComparisonResult = o1.getName().compareToIgnoreCase(o2.getName());
return 0 == nameComparisonResult?o1.getAge()-o2.getAge():nameComparisonResult;
}
}
16条答案
按热度按时间pkln4tw61#
或者你可以利用
Collections.sort()
(或Arrays.sort()
)是稳定的(它不会对相等的元素重新排序)并使用Comparator
先按年龄排序,再按姓名排序。在这种情况下,这不是一个很好的主意,但如果您必须能够在运行时更改排序顺序,它可能会很有用。
lnxxn5zx2#
我会小心使用Guava
ComparisonChain
因为它会为每个被比较的元素创建一个示例,所以您将看到N x Log N
比较链只是为了在排序时进行比较,或者N
如果您正在迭代并检查相等性,则返回一个示例。我会创建一个静态
Comparator
尽可能使用最新的Java8API或guava的Ordering
允许您这样做的api,下面是java 8的一个示例:下面是如何使用Guava的
Ordering
应用程序编程接口:https://github.com/google/guava/wiki/orderingexplained0aydgbwb3#
在这种情况下,我不确定在person类中编写比较器是否丑陋。是这样的:
e3bfsja24#
为了一节课
Book
这样地:用模拟对象排序主类
r6l8ljro5#
你可以这样做:
g6ll5ycj6#
可以使用通用串行比较器按多个字段对集合进行排序。
b4wnujal7#
让person类实现
Comparable<Person>
然后实现compareto方法,例如:这将首先按姓名(不区分大小写)排序,然后按年龄排序。然后你就可以跑了
Arrays.sort()
或者Collections.sort()
在person对象的集合或数组上。qojgxg4l8#
你可以用
Collections.sort
具体如下:gkn4icbw9#
Guava
ComparisonChain
提供了一种干净的方法。请参阅此链接。用于执行链式比较语句的实用程序。例如:
31moq8wy10#
使用
Comparator
然后把东西放进Collection
,那么Collections.sort();
```class Person {
}
public class Main{
}
o8x7eapl11#
根据需要创建尽可能多的比较器。之后,为每个订单类别调用方法“thencomparing”。这是一种顺流而下的方式。请参见:
查看:在多个字段上对用户定义的对象排序–comparator(lambda流)
iugsix8n12#
你需要实现你自己的
Comparator
,然后使用它:例如你的比较仪可能看起来有点像这样:
比较器首先比较姓名,如果姓名不相等,则返回比较结果,否则在比较两个人的年龄时返回比较结果。
这段代码只是一个草稿:因为类是不可变的,所以您可以考虑构建它的一个单例,而不是为每个排序创建一个新示例。
m3eecexj13#
对于那些能够使用Java8StreamingAPI的人来说,有一种更整洁的方法在这里有很好的文档记录:lambdas和排序
我在寻找c#linq的等价物:
我在比较器上发现了java 8中的机制:
下面是演示算法的片段。
请查看上面的链接,以获得更简洁的方式,并解释java的类型推断如何使定义比linq更笨拙。
以下是完整的单元测试供参考:
lb3vh1jj14#
使用Java8流方法。。。
Java8Lambda方法。。。
最后。。。
polhcujo15#
更新版本: