Java对象排序之Comparator与Comparable

前言

关于Java中的排序,我们常见的就是对ArrayList进行排序,对于Array,我们可以使用Arrays.sort(数组)进行排序;对于List,我们可以使用Collections.sort(list)进行排序,如果是需要对一个实体类的对象进行排序呢?

两种实现方法

有两种方法可以实现。

  1. 一种方法是类实现Comparable<T>接口,然后调用Collections.sort(List)方法进行排序。
  2. 另一种方法是类不实现Comparable接口,而在排序时使用Collections.sort(List, Comparator<T>)方法,并实现其中的Comparator<T>接口。

Comparable接口有一个comparTo(Object o)方法,它返回整数类型。对于表达式x.compareTo(y),**如果返回值为0,则表示x和y相等,如果返回值大于0,则表示x大于y,如果返回值小于0,则表示x小于y;**这是一个比较器接口。

排序实现

模拟一个Person对象,要对其进行排序,排序的条件是先根据id排序,当id相等的情况下载根据年龄进行排序,当年龄相等再根据名字。

通过类实现Comparable接口进行排序

Person类

public static class Person implements Comparable<Person> {
		//非 int、float等基本类型
		private Integer id;
		private Integer age;
		private String name;

		public Person(Integer age, String name, Integer id) {
			this.age = age;
			this.name = name;
			this.id = id;
		}

		public Integer getId() {
			return id;
		}

		public void setId(Integer id) {
			this.id = id;
		}

		public Integer getAge() {
			return age;
		}

		public void setAge(Integer age) {
			this.age = age;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		@Override
		public String toString() {
			return "Person [id=" + id + ", age=" + age + ", name=" + name + "]";
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.Comparable#compareTo(java.lang.Object)
		 * 先根据id比较,如果id相同,就比较age,最后再比较name(按姓名的字典序升序排序)
		 */
		@Override
		public int compareTo(Person o) {
			if (this.id > o.getId()) {
				return 1;
			} else if (this.id < o.getId()) {
				return -1;
			} else {
				if (this.age > o.getAge()) {
					return 1;
				} else if (this.age < o.getAge()) {
					return -1;
				} else {
					return this.name.compareTo(o.getName());
				}
			}
		}

	}

在客户端中测试

public class Compareto {
	public static void main(String[] args) {
        List<Person> students = new ArrayList<>();
        students.add(new Person(25, "LuanYu",0));
        students.add(new Person(26, "LuanYu",0));
        students.add(new Person(26, "LuanYu",5));
        students.add(new Person(27, "LiuBei",1));
        students.add(new Person(27, "Zhangi",1));

        Collections.sort(students);
        for(Person student:students){
            System.out.println(student.toString());
        }
	}

输出结果

Person [id=0, age=25, name=LuanYu]
Person [id=0, age=26, name=LuanYu]
Person [id=1, age=27, name=LiuBei]
Person [id=1, age=27, name=Zhangi]
Person [id=5, age=26, name=LuanYu]

可以看到,按姓名的字典序升序排序。使用这用方法排序不能使用基本类型(int, float)等。

通过Comparable接口实现排序

Person类

/**
	 * 没有实现Comparable<T>接口的Person类
	 */
	public static class Person {
		private Integer id;
		private Integer age;
		private String name;

		public Person(Integer age, String name, Integer id) {
			this.age = age;
			this.name = name;
			this.id = id;
		}

		@Override
		public String toString() {
			return "Person [id=" + id + ", age=" + age + ", name=" + name + "]";
		}

		public Integer getId() {
			return id;
		}

		public void setId(Integer id) {
			this.id = id;
		}

		public Integer getAge() {
			return age;
		}

		public void setAge(Integer age) {
			this.age = age;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

	}

main方法

public static void main(String[] args) {
		List<Person> persons = new ArrayList<>();
		persons.add(new Person(25, "LsanYu", 0));
		persons.add(new Person(26, "LuanYu", 0));
		persons.add(new Person(26, "LuanYu", 5));
		persons.add(new Person(27, "LiuBei", 1));
		persons.add(new Person(27, "Zhangi", 1));

		Collections.sort(persons, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
//            	这里是需要做处理的部分
            	if (o1.getId() > o2.getId()) {
					return 1;
				}else if (o1.getId() < o2.getId()) {
					return -1;
				}else {
					if (o1.getAge()>o2.getAge()) {
						return 1;
					}else if (o1.getAge() < o2.getAge()) {
						return -1;
					}else {
						 return o1.getName().compareTo(o2.getName());
					}
				}
            }
        });
        for(Person person:persons){
            System.out.println(person.toString());
        }
	}

输出结果

Person [id=0, age=25, name=LsanYu]
Person [id=0, age=26, name=LuanYu]
Person [id=1, age=27, name=LiuBei]
Person [id=1, age=27, name=Zhangi]
Person [id=5, age=26, name=LuanYu]

总结

  1. 第二种方法通过重新定义Collections.sort(List,Comparator)实现排序,当需求有变需要按照其他规则(比如id)排序时,只有重新定义一个Comaprator,而不用修改Person类,然后修改客户端代码,这样就基本满足了开闭原则,即可以通过增加新类方便的扩充新功能,满足新需求而不用修改原来的代码。
  2. 如果我们采用让Person实现Comaparable接口,则在想采用新的排序规则时,必须修改Person里的comareTo(Object o)方法,这样就违反了开闭原则。综上,第二种方法比第一种方法更加灵活。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章