Java中对集合进行排序的两种方法

Java中对集合进行排序的两种方法

Collections是集合的工具类,它提供了很多便于我们操作集合的方法, 其中就有用于集合排序的sort方法。

实际上,在使用Collection的sort排序的集合元素都必须是Comparable接口的实现类,该接口表示子类是可以比较的。因为实现接口必须重写抽象方法 - int compareTo(T t)。

一、 对于集合的比较

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

import java.util.Random;

public class Test1 {

public static void main(String[] args) {

List list0 = new ArrayList<>();

Random random = new Random();

for(int i = 0; i<10;i++){

list0.add(random.nextInt(100));

}

System.out.println(list0);//[46, 7, 91, 48, 52, 25, 64, 3, 28, 60]

/*

* 对集合进行自然排序,从小到大

*/

Collections.sort(list0);

System.out.println(list0);//[2, 19, 44, 46, 61, 67, 68, 89, 91, 94]

List list1 = new ArrayList<>();

list1.add("Alive");

list1.add("Rose");

list1.add("Jack");

list1.add("Noname");

System.out.println(list1);//[Alive, Rose, Jack, Noname]

Collections.sort(list1);

/*

*对集合进行自然排序,显而易见是按照首字母顺序排序

*/

System.out.println(list1);//[Alive, Jack, Noname, Rose]

}

}

那么你有没有发现在该类中我并没有实现Comparable接口,那么为什么

我对list0和list1集合排序时没有报错呢?

原因:查询源码可知Integer、String类都实现了Comparable接口,所以在对list0和list1集合排序时没有报错。

二、对于集合中的对象比较(自定义排序)

那么问题来了对象这个大小之分是如何判断呢?

* 实际上,在使用Collection的sort排序的集合元素都必须是Comparable接口的实现类,该接口

* 表示子类是可以比较的。

* 因为实现接口必须重写抽象方法。

* - int compareTo(T t);

* 该方法用于使当前对象与给定对象进行比较。

* 返回值为一个int值,该值表示大小关系,它不关注具体的取值是多少,而关注的是取值范围。

* 当返回值>0时:当前对象比参数对象大

* 当返回值<0时:当前对象比参数对象小

* 当返回值=0时:当前对象等于参数对象

Cell类:

public class Cell implements Comparable{//哪个类实现Comparable接口泛型就写哪个类

private int x;

private int y;

public Cell(int x, int y) {

super();

this.x = x;

this.y = y;

}

/**

* @return the x

*/

public int getX() {

return x;

}

/**

* @param x the x to set

*/

public void setX(int x) {

this.x = x;

}

/**

* @return the y

*/

public int getY() {

return y;

}

/**

* @param y the y to set

*/

public void setY(int y) {

this.y = y;

}

@Override

public String toString() {

return "Cell [x=" + x + ", y=" + y + "]";

}

@Override

public int compareTo(Cell o) {//自定义排序逻辑

// TODO Auto-generated method stub

return this.x-o.x;//以传入的Cell的横坐标由小到大进行排序

}

}

@Test

public void testComparable(){

/*

* Cell实现了Comparable接口,compareTo方法逻辑为按照x值大小进行排序

*/

List cells = new ArrayList();

cells.add(new Cell(2,3));

cells.add(new Cell(5,1));

cells.add(new Cell(3,2));

System.out.println(cells);//[Cell [x=2, y=3], Cell [x=5, y=1], Cell [x=3, y=2]]

Collections.sort(cells);

System.out.println(cells);//[Cell [x=2, y=3], Cell [x=3, y=2], Cell [x=5, y=1]]

}

我们想使用sort方法排序集合,但是该方法要求我们的集合元素必须实现Comparable接口并且定义比较规则,这种我们想使用某个功能,而它要求我们修改程序的现象称为“侵入性”。修改的代码越多,侵入性比较强,越不利于程序的扩展。

所以不建议使用这个构造方法。

三、使用重载的Collections.sort(List,Comparator)方法

* 重载的sort方法要求传入一个额外的比较器

* 该方法不再要求集合元素必须实现Comparable接口,

* 并且也不再使用集合元素自身的比较规则排序了,而是根据给定的这个额外的比较器的比较规则

* 对集合元素进行排序。

* 实际开发中也推荐使用这种方式排序集合元素,若集合元素是自定义的,创建比较器时也推荐使用匿名内部类

* 的形式。

方法一:自定义一个比较器然后传入

Collections.sort(List,Comparator)中。

测试代码:

自定义的比较器:

import java.util.Comparator;

public class MyComparator implements Comparator{

@Override

public int compare(Cell o1, Cell o2) {

return o1.getY()-o2.getY();//根据传入的cell的y坐标由小到大进行排序

}

}

测试类:

@Test

public void testComparator() {

List cells = new ArrayList<>();

cells.add(new Cell(2,3));

cells.add(new Cell(5,1));

cells.add(new Cell(3,2));

System.out.println(cells);//[Cell [x=2, y=3], Cell [x=5, y=1], Cell [x=3, y=2]]

MyComparator com = new MyComparator();

Collections.sort(cells,com);

System.out.println(cells);//根据自定义排序后的结果:[Cell [x=5, y=1], Cell [x=3, y=2], Cell [x=2, y=3]]

}

方法二:采用匿名内部的形式(推荐做法)

@Test

public void testComparator() {

List cells = new ArrayList<>();

cells.add(new Cell(2,3));

cells.add(new Cell(5,1));

cells.add(new Cell(3,2));

System.out.println(cells);//[Cell [x=2, y=3], Cell [x=5, y=1], Cell [x=3, y=2]]

Collections.sort(cells,new Comparator(){//此处创建了一个匿名内部类

@Override

public int compare(Cell o1,Cell o2){

return o1.getY() - o2.getY();

}

});

System.out.println(cells);//[Cell [x=5, y=1], Cell [x=3, y=2], Cell [x=2, y=3]]

}

比较总结:

*1.对于集合比较使用Collections.sort();

*2.对于集合中的对象比较,需要指定比较逻辑,指定比较逻辑需要实现 Comparable接口并重写compareTo方法自定义逻辑。

*3.对于需要临时改变比较规则,需要使用Collections.sort(List,Comparator),采用回调方式重写Comparator接口的compare方法自定义逻辑。

评论留言