sort是进行collection集合进行排序使用的方法。会自动调用compareTo()方法,对集合进行排序。
一般步骤:
要排序的类要实现Comparable<?>接口,然后重写compareTo()方法;最后再调用sort(Collection)方法。调用sort()方法以后,sort()方法会自动调用compareTo()方法。
sort源码:实力尚浅,暂不分析。
代码:
public class CollectionTest1 implements Comparable<CollectionTest1>{
private String name;
private Integer age;
private String gender;
public CollectionTest1() {
}
public CollectionTest1(String name, Integer age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "CollectionTest1{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
@Override
public int compareTo(CollectionTest1 person) {
if (person.age>this.age){
return 1;
}else if (person.age==this.age){
return 0;
}else {
return -1;
}
}
public static void main(String[] args) {
List<CollectionTest1> list = new ArrayList<>();
list.add(new CollectionTest1("张三",20,"男"));
list.add(new CollectionTest1("李四",24,"男"));
list.add(new CollectionTest1("王五",23,"女"));
list.add(new CollectionTest1("赵六",26,"男"));
list.add(new CollectionTest1("孙七",18,"女"));
list.add(new CollectionTest1("周八",18,"女"));
System.out.println("排序前:");
for (CollectionTest1 collectionTest1 : list) {
System.out.println(collectionTest1.toString());
}
Collections.sort(list);
System.out.println("排序后:-----------------------------------------");
for (CollectionTest1 collectionTest1 : list) {
System.out.println(collectionTest1.toString());
}
说明:
实现Comparable<T>接口之后,compareTo()方法必须要被重写,增加业务逻辑。
浅析compareTo()方法:
(本人目前是个初学者,看不太明白源码,只能是自话自说,如与事实不符,敬请在评论区斧正!)
一般compareTo()方法中,进行排序的业务代码都是返回1,0,-1。其中this代指即将传入的对象,然后.出可比较的属性。
返回1就代表 要比较的元素在被比较元素 的后面,继续向后比较;
返回-1就代表 要比较的元素在被比较元素 的前面,不再继续向后比较;
返回0就代表 要比较的元素和被比较元素 相等,先来后到,放在被比较数的后面,不再向后比较;
用目前的眼光看来,比较时与List集合中的元素逐个比较(一开始是空的),比较后的数据按顺序放在此List集合中。
规则:
this.属性>集合传入对象.属性,返回1;
this.属性==集合传入对象.属性,返回0;
this.属性<集合传入对象.属性,返回-1。
这样排的顺序是从小到大排列;
反过来:
this.属性<集合传入对象.属性,返回1;
this.属性==集合传入对象.属性,返回0;
this.属性>集合传入对象.属性,返回-1。
这样的排序是从大到小排列。
下面为个人理解:
在重写compareTo()方法时,传入的对象规定List集合的类型,初始化为空List对象集合。等比较的时候,将传入的属性值与List集合中的元素对应属性值进行逐个比较,以此来确定将要存放的位置。所以速度较慢。
以上述代码中例子为例:根据年龄age排序
第一次比较:this.age是20,person.age是List<CollectionTest1>中取出的元素对象属性值,一开始没有数据,所以为null,看作0。this.age>person.age,返回1,现在的List集合中[20];
第二次比较:this.age是24,person.age是20,this.age>person.age,返回-1,现在List集合中[24,20];
第三次比较:this.age是23,第一个person.age是24,this.age<person.age,返回1;第二个person.age是20,this.age>person.age,返回-1。现在List集合中[24,23,20];
第四次比较:this.age是26,第一个person.age是24,this.age>person.age,返回-1;现在List集合中[26,24,23,20];
第五次比较:this.age是18,第一个person.age是26,this.age<person.age,返回1,继续比较;
第二个person.age是24,this.age<person.age,返回1,继续比较;
第三个person.age是23,this.age<person.age,返回1,继续比较;
第四个person.age是20,this.age<person.age,返回1,继续比较;
这时候List集合已经没有可以比较的元素了,所以
第五个person.age是null,看作0,this.age>person.age,返回-1,停止比较;
现在List集合中[26,24,23,20,18];
第六次比较,this.age是18,第一个person.age是26,this.age<person.age,返回1,继续比较;
第二个person.age是24,this.age<person.age,返回1,继续比较;
第三个person.age是23,this.age<person.age,返回1,继续比较;
第四个person.age是20,this.age<person.age,返回1,继续比较;
第五个person.age是18,this.age==person.age,返回0,直接放在被比较数的后面,停止比较;
现在List集合中[26,24,23,20,18,18];
所以排序后,遍历结果是 26,24,23,20,18,18 对应的元素对象。
max和min:
源码:
---------------------max----------------------------
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
Iterator<? extends T> i = coll.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;
}
-------------------min----------------------------
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) {
Iterator<? extends T> i = coll.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) < 0)
candidate = next;
}
return candidate;
}
Collections中的max()和min()方法根据compareTo()中的规则进行判断取值。规则写反,就取反。
为何写反取反?因为源码中判断是这样的:根据返回值来判断,然后赋值。
比如max方法中:
先是定义迭代器Iterator迭代集合元素,然后定义一个变量candidate,接收next()指针指向的当前元素。
紧接着开始使用while遍历集合,新定义一个变量next,将指针指向的当前元素赋值给它。
然后使用我们重写的compareTo()方法进行if条件分支判断,注意,这里是next在前,candidate在后进行比较。若后一个元素与前一个元素的compareTo()方法返回的值是1,证明前一个元素大于后一个元素,而1>0为true,则将后一个元素next的值赋给前一个元素candidate。若为false则不赋值。然后直到遍历完成,返回candidate。
min方法同理。写反取反。
所以会出现下面的结果:
年龄最大:CollectionTest1{name='周八', age=18, gender='女'}
年龄最小:CollectionTest1{name='赵六', age=26, gender='男'}