Java中List对象集合按照对象某一属性字段排序

Posted luffy5459

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中List对象集合按照对象某一属性字段排序相关的知识,希望对你有一定的参考价值。

    Java中,List集合对象,默认有一个排序方法sort(Comparator<? super E> c),如果传递null,那是对简单类型的排序,如果是对象类型,并且是需要按照对象类型的某一个属性字段排序,就需要我们传入排序的规则。

    show me the code:

package com.xxx.huali.hualitest.sort;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ListSort {
	public static void main(String[] args) {
		List<Person> list = new ArrayList<Person>();
		list.add(new Person(1,"jack",18));
		list.add(new Person(2,"paul",28));
		list.add(new Person(3,"zion",20));
		list.add(new Person(4,"jone",30));
		list.forEach(System.out::println);
		//利用Collections.sort方法按照年龄排序,默认升序
		Collections.sort(list, (a,b)->{
			return a.getAge() - b.getAge();
		});
		System.out.println("================================");
		list.forEach(System.out::println);
		//直接使用List集合sort方法按照姓名排序,默认字母升序
		list.sort((a,b)->a.getName().compareTo(b.getName()));
		System.out.println("================================");
		list.forEach(System.out::println);
	}
}

class Person{
	private int id ;
	private String name ;
	private int age;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
	}
	
	public Person() {
		
	}
	
	public Person(int id,String name,int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}
}

    示例中,定义了Person对象,分别按照年龄和姓名排序,运行程序,打印结果如下:

Person [id=1, name=jack, age=18]
Person [id=2, name=paul, age=28]
Person [id=3, name=zion, age=20]
Person [id=4, name=jone, age=30]
================================
Person [id=1, name=jack, age=18]
Person [id=3, name=zion, age=20]
Person [id=2, name=paul, age=28]
Person [id=4, name=jone, age=30]
================================
Person [id=1, name=jack, age=18]
Person [id=4, name=jone, age=30]
Person [id=2, name=paul, age=28]
Person [id=3, name=zion, age=20]

    排序思路很简单,就是利用List集合自带的sort函数,传入相应的比较函数。

    有意思的是,Set集合,是一个不重复的集合,但是它就没有sort排序方法。

     上面的排序算法,我们传入了排序函数,是使用的lambda表达式的形式,这个是在jdk8以后的版本中才能使用,传统的做法这里其实是需要传入一个匿名内部类Comparator。

list.sort(new Comparator<Person>() {

	@Override
	public int compare(Person o1, Person o2) {
		return o1.getId() - o2.getId();
	}
			
});

      另外,数组对象排序,可以使用Arrays.sort()方法,这个方法的对象不能是集合,只能是数组。

package com.xxx.huali.hualitest.sort;
import java.util.Arrays;
public class ArraySort {
	public static void main(String[] args) {
		Employee[] emps = new Employee[] {new Employee(1, "jack", 5000),
				new Employee(2,"ivan",2888),
				new Employee(4, "lisa", 3000),
				new Employee(3, "lucy", 9999)};
		for (int i = 0; i < emps.length; i++) {
			System.out.println(emps[i]);
		}
		Arrays.sort(emps);
	}
}

class Employee{
	private int id;
	private String name;
	private double salary;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
	}
	
	public Employee() {
		// TODO Auto-generated constructor stub
	}
	
	public Employee(int id,String name,double salary) {
		this.id = id;
		this.name = name;
		this.salary = salary;
	}
}

    运行代码,报错:

Exception in thread "main" java.lang.ClassCastException: com.xxx.huali.hualitest.sort.Employee cannot be cast to java.lang.Comparable
    at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:320)
    at java.util.ComparableTimSort.sort(ComparableTimSort.java:188)
    at java.util.Arrays.sort(Arrays.java:1246)
    at com.xxx.huali.hualitest.sort.ArraySort.main(ArraySort.java:12)

   根据提示,Employee对象不能转为Comparable类型。修改代码,实现Comparable接口,并覆盖方法。

package com.xxx.huali.hualitest.sort;
import java.util.Arrays;
public class ArraySort {
	public static void main(String[] args) {
		Employee[] emps = new Employee[] {new Employee(1, "jack", 5000),
				new Employee(2,"ivan",2888),
				new Employee(4, "lisa", 3000),
				new Employee(3, "lucy", 9999)};
		for (int i = 0; i < emps.length; i++) {
			System.out.println(emps[i]);
		}
		Arrays.sort(emps);
		System.out.println("=========================================");
		for (int i = 0; i < emps.length; i++) {
			System.out.println(emps[i]);
		}
	}
}

class Employee implements Comparable<Employee>{
	private int id;
	private String name;
	private double salary;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
	}
	
	public Employee() {
		// TODO Auto-generated constructor stub
	}
	
	public Employee(int id,String name,double salary) {
		this.id = id;
		this.name = name;
		this.salary = salary;
	}
	@Override
	public int compareTo(Employee o) {
		return (int)(this.salary - o.getSalary());
	}
}

    运行代码,打印结果如下:

Employee [id=1, name=jack, salary=5000.0]
Employee [id=2, name=ivan, salary=2888.0]
Employee [id=4, name=lisa, salary=3000.0]
Employee [id=3, name=lucy, salary=9999.0]
=========================================
Employee [id=2, name=ivan, salary=2888.0]
Employee [id=4, name=lisa, salary=3000.0]
Employee [id=1, name=jack, salary=5000.0]
Employee [id=3, name=lucy, salary=9999.0]

    从上面的这个数组集合排序的例子中,我们可以得出一个结论,我们如果要让Arrays.sort()方法发挥作用,需要让对象实现Comparable接口,那么实现了Comparable接口的对象,是否在List.sort()方法中,可以默认排序呢,答案是肯定的。

package com.xxx.huali.hualitest.sort;
import java.util.Arrays;
import java.util.List;
public class ArraySort {
	public static void main(String[] args) {
		Employee[] emps = new Employee[] {new Employee(1, "jack", 5000),
				new Employee(2,"ivan",2888),
				new Employee(4, "lisa", 3000),
				new Employee(3, "lucy", 9999)};
		/*
		for (int i = 0; i < emps.length; i++) {
			System.out.println(emps[i]);
		}
		Arrays.sort(emps);
		System.out.println("=========================================");
		for (int i = 0; i < emps.length; i++) {
			System.out.println(emps[i]);
		}*/
		
		List<Employee> list = Arrays.asList(emps);
		list.forEach(System.out::println);
		System.out.println("=========================================");
		list.sort(null);
		list.forEach(System.out::println);
	}
}

class Employee implements Comparable<Employee>{
	private int id;
	private String name;
	private double salary;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
	}
	
	public Employee() {
		// TODO Auto-generated constructor stub
	}
	
	public Employee(int id,String name,double salary) {
		this.id = id;
		this.name = name;
		this.salary = salary;
	}
	@Override
	public int compareTo(Employee o) {
		return (int)(this.salary - o.getSalary());
	}
}

    排序结果:

Employee [id=1, name=jack, salary=5000.0]
Employee [id=2, name=ivan, salary=2888.0]
Employee [id=4, name=lisa, salary=3000.0]
Employee [id=3, name=lucy, salary=9999.0]
=========================================
Employee [id=2, name=ivan, salary=2888.0]
Employee [id=4, name=lisa, salary=3000.0]
Employee [id=1, name=jack, salary=5000.0]
Employee [id=3, name=lucy, salary=9999.0]

     结果与上面通过Arrays.sort()对数组对象排序结果是一样的。

     通过前面的介绍,我们知道,对象类型排序,需要实现排序函数,也就是指定排序规则,他们都需要实现Comparable接口或者Comparator接口。

      那么,Comparable vs Comparator:

      1、Comprable接口一旦实现,只能提供一种排序规则,而Comparator可以以匿名内部类的形式提供多种排序方法。

      2、使用Comparable接口,需要实现它,而使用Comparator接口,我们无需对原始类作改动,在类中添加额外代码。

      3、Comparable接口是在java.lang包中,而Comparator接口在java.util包中。

      4、 Comparable接口已经侵入类中,所以类默认有了排序规则,所以我们在使用排序算法的时候,不需要传入排序函数,自动使用默认排序compareTo()函数,而使用Comparator接口,我们需要在排序的地方提供compare()函数。

    本文编写过程中参照了一些其他资料:

    Comparable and Comparator in Java Example - JournalDev

     

以上是关于Java中List对象集合按照对象某一属性字段排序的主要内容,如果未能解决你的问题,请参考以下文章

java list按照元素对象的指定多个字段属性进行排序

java list按照元素对象的指定多个字段属性进行排序

Java关于list集合根据集合元素对象的某个或多个属性进行排序的工具类

java 如何判断list里某一字段值全部相等

List集合根据存储对象的属性字段排序实现

java按照list集合中的对象属性进行去重