Java List 排序

1、进行List排序的元素,必须实现Comparable接口。

像List<Integer>、List<String>我们可能会有这样的感觉: 我并没有做任何操作,直接Collections.sort() 就可以排序啊。

其实那是因为Integer、String早已经实现了Comparable接口,我们看下Integer、String的源码:

public final class Integer extends Number implements Comparable<Integer> {
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {

2、看下Integer、String是根据什么进行排序的,也就是实现的compareTo方法,这对我们进行自定义对象排序有很好的借鉴作用。

      我们先看下Integer类型的:

public int compareTo(Integer anotherInteger) {
     return compare(this.value, anotherInteger.value);
}

 public static int compare(int x, int y) {
     return (x < y) ? -1 : ((x == y) ? 0 : 1);
 }

   它的compareTo方法中调用自己的compare方法,其实就是比较大小来排序。我们再看下String类型的:

public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
 }

  它先拿到要比较的两个Sting的长度,然后取两个长度中最小的一个,然后循环两个char数组,如果两个char不相等,则比较结束。只有前面元素都一致导致比较不出来结果时再根据长度来比较,所以并不是一般认为的长度越长肯定排序越靠后。比如'A'的ASCII码是65,'a'的ASCII码是97,所以如果一个是A开头的字符串,一个是a开头的字符串,不管长度多少,sort排序后肯定是a开头的字符串排在后面。举例说明下:

       

  List<String> list = new ArrayList<String>();
  list.add("aa");
  list.add("AAA");
  list.add("bb");
  list.add("ab");
  list.add("abb");
  Collections.sort(list);
  System.out.println(list);

最后排序结果是: [AAA, aa, ab, abb, bb]

3、我们一般用到的都是List保存的是自定义对象,或者是Map结构,通过实现Comparable接口来排序。

    我们有一个Student类,里面有4个属性: id、name、age、score,分别表示学号、姓名、年龄、综合评分。我们有一个这样的需求: 先按照学生的年龄排序再根据评分排序,我们看如何实现。

     首先我们要把类实现Comparable接口,然后重写compareTo方法,代码如下:

public class Student implements Comparable<Student>{

	private Integer id;
	private String name;
	private Integer age;
	private Integer score;
	
	public Student(Integer id, String name, Integer age, Integer score){
		this.id = id;
		this.name = name;
		this.age = age;
		this.score = score;
	}
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Integer getScore() {
		return score;
	}
	public void setScore(Integer score) {
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age
				+ ", score=" + score + "]";
	}
	@Override
	public int compareTo(Student o) {
		
		int i = this.getAge() - o.getAge(); // 先根据年龄排序
		if(i == 0){
			return this.score - o.getScore(); //年龄相当则根据评分排序
		}
		
		return i;
	}
	
}

  然后写一个测试类来验证:

public class TestStudent {
	
	public static void main(String[] args) {
		
		Student s1 = new Student(1, "张三", 20, 89);
		Student s2 = new Student(2, "李四", 21, 97);
		Student s3 = new Student(3, "王五", 20, 70);
		Student s4 = new Student(4, "赵六", 21, 85);
		List<Student> list = new ArrayList<Student>();
		list.add(s3);
		list.add(s1);
		list.add(s2);
		list.add(s4);
		Collections.sort(list);
		System.out.println(list);
		
	}

}

    排序结果:

[Student [id=3, name=王五, age=20, score=70],

Student [id=1, name=张三, age=20, score=89],

Student [id=4, name=赵六, age=21, score=85],

Student [id=2, name=李四, age=21, score=97]]

这种排序一般被我们称为自然排序,下面我们说另一种实现方式,一般称为定制排序。

4、通过匿名内部类,实现Comparator接口的类来实现排序,这种实现方式一般称为定制排序。

这种方式一般更适合List<Map>这种结构,当然像List<Student>这种也可以用这种方式实现。实际项目中比如我们通过接口获取了一部分数据,接口返回结果是Json结构,我们把相应的数据转为List<Map>这种结构,但是接口返回的数据并不是按照我们想要的顺序来排序的,需要我们再次排序,这个时候我们就需要用到定制排序了。

Collections.sort(askList, new Comparator<Map<String, Object>>(){
	  public int compare(Map<String, Object> map1, Map<String, Object> map2) {
		  long d1 = Long.parseLong(map1.get("updateTime").toString());
		  long d2 = Long.parseLong(map2.get("updateTime").toString());
		  if((d1- d2) < 0){
			  return 1;
		  }
		  if((d1- d2) == 0){
			  return 0;
		  }
		  return -1;
	   }
}); 

  askList就是返回接口的List<Map>集合,我们希望按照里面的一个字段updateTime(最后更新时间)来排序。

 

希望对你有帮助,欢迎批评指正讨论。欢迎关注我的微信公众号:javaSharing。

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值