使用Collections提供的sort方法,对集合进行排序
Collections.sort(list);
实现原理:
将list转成了数组对象后,调用了Array的sort方法,将数组排序,再用list的迭代器(注意不是collection迭代器)一个个得赋值回去,就使得传入的list变成了一个有序的list
public class SortListDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Random random = new Random();
//随机生成一个数,作为list元素
for(int i=0;i<10;i++){
//向末尾添加随机的数
list.add(random.nextInt(100));
}
System.out.println(list);
//使用Collections提供的sort方法,对集合进行排序
Collections.sort(list);
System.out.println(list);
}
}
它提供了对集合对象进行基本操作的通用接口方法
Collection接口在Java 类库中有很多具体的实现
Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式
它包含有各种有关集合操作的静态多态方法
此类不能实例化,就像一个工具类,服务于Java的Collection框架
Comparable接口:
Collections的sort方法是对集合元素进行自然排序
在使用Collections的sort排序的集合元素都必须是Comparable接口的实现类
该接口表示其子类是可比较的,因为实现该接口必须重写抽象方法 int compareTo(T t);
这个接口用于给需要排序的类来实现的,一旦实现,这个类就会按这个方式排序
比如说我们常见的String类就实现了这个接口,并重写了里面的compareTo
所以我们对字符串可以利用compareTo方法进行排序
Comparator接口(一般用这种):
一旦Java类实现了Comparable接口,其比较逻辑就已经确定(只能按写在自定义类中的算法排序)
如果希望在排序的操作中临时指定比较规则,可以采用Comparator接口回调的方式。
Comparator接口要求实现类必须重写其定义的方法 int compare(T o1,T o2)
通过比较器比较自定义类
自定义排序必须提供比较器
比较器为一个自定义的实现了比较器的类的实例化对象
自定义排序语法
Collections.sort(list,比较器);
① 自定义一个比较器类,实现比较器的接口(Comparator 尖括号里面传入比较器比较的类)
注意:必须重写compare方法,返回值为int
然后使用Collections.sort时,在括号里传入需要排序的列表和new一个自定义比较器类的实例对象
Collections.sort(list, new ByAge());
② 匿名内部类(上班后常用,记得简写),实现原理同上
//使用匿名内部类排序
Comparator<Person> byAge = new Comparator<Person>(){
@Override
public int compare(Person o1, Person o2) {
return o1.age-o2.age;
}
};
//按照匿名内部类比较器规则进行年龄排序
//这里只需要把刚才的内部类对象传递进来就行了
Collections.sort(list,byAge);
System.out.println(list);
//上班后上述匿名内部类代码可以简化为
Collections.sort(list,new Comparator<Person>(){
public int compare(Person o1, Person o2){
return o1.age-o2.age;
}
});
System.out.println(list);
//匿名内部类实现,按名字顺序比较
Collections.sort(list,new Comparator<Person>(){
public int compare(Person o1, Person o2) {
//compareTo 按字典顺序比较两个字符串(字符编码)
return o1.name.compareTo(o2.name);
}
});
System.out.println(list);
package collection.comparator;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* 自定义排序(通过比较器比较自定义类)
* @author Tian
*
*/
public class SortListDemo {
public static void main(String[] args) {
/*
* 对一组人进行自定义排序
*/
List<Person> list = new ArrayList<>();
list.add(new Person("徐凤年",23,130));
list.add(new Person("姜泥",20,96));
list.add(new Person("裴南苇",32,98));
list.add(new Person("洛阳",800,100));
/*
* 自定义排序必须提供比较器
* 比较器为一个自定义的实现了比较器的类的实例化对象
*/
//Collections.sort(list,比较器);
//按照自定义比较器规则进行年龄排序
Collections.sort(list, new ByAge());
System.out.println(list);
//按照自定义比较器规则进行体重排序
Collections.sort(list, new ByWeight());
System.out.println(list);
//使用匿名内部类排序
Comparator<Person> byAge = new Comparator<Person>(){
@Override
public int compare(Person o1, Person o2) {
return o1.age-o2.age;
}
};
//按照匿名内部类比较器规则进行年龄排序
//这里只需要把刚才的内部类对象传递进来就行了
Collections.sort(list,byAge);
System.out.println(list);
//上班后上述匿名内部类代码可以简化为
Collections.sort(list,new Comparator<Person>(){
public int compare(Person o1, Person o2){
return o1.age-o2.age;
}
});
System.out.println(list);
//匿名内部类实现,按名字顺序比较
Collections.sort(list,new Comparator<Person>(){
public int compare(Person o1, Person o2) {
//compareTo 按字典顺序比较两个字符串(字符编码)
//详情见拓展
return o1.name.compareTo(o2.name);
}
});
System.out.println(list);
//按名字拼音的首字母排序
//创建了一个字符串的列表,用来接收人类中的姓名
List<String> str = new ArrayList<>();
//循环遍历人类列表,将姓名放到字符串列表中
for(Person p : list){
str.add(p.name);
}
//使用比较器对名字列表进行排序
/*
* Collator.getInstance(java.util.Locale.CHINA)
* 这个方法是
* Collator类调用了一下他的工厂方法(静态方法的一种常见用途)
* 该方法会返回一个比较器的对象,内部实现了按字符串首字符的拼音首字母排序
* 这个方法需要传入一个参数,语言包,我们这里传入的是中文
*/
Collections.sort(str,Collator.getInstance(java.util.Locale.CHINA));
//输出排序后的字符串列表
System.out.println(str);
//问题:只能修改String列表,怎么把这个修改顺序的影响扩大到Person列表中呢
}
}
/**
* 根据年龄比较两人的比较器
* 自定义比较器,实现比较器的接口
* Comparator
* 尖括号里面传入比较器比较的类
*/
class ByAge implements Comparator<Person>{
/**
* 重写接口里面的比较方法
* 注意:该方法返回值需要有三个状态(0、正数、负数)
*/
@Override
public int compare(Person o1, Person o2) {
//按照两个人的年龄比较
// if(o1.age == o2.age){
// return 0; //返回0,表示人类o1与o2年龄一样
// }else if(o1.age > o2.age){
// return 1; //返回正数,表示01大于o2年龄
// }else{
// return -1; //返回负数,表示o1年龄小于o2年龄
// }
//可以优化为
return o1.age-o2.age;
//倒叙可以写为
//return -(o1.age-o2.age);
}
}
/**
* 根据体重排序的比较器
*/
class ByWeight implements Comparator<Person>{
/**
* 比较体重的比较器
* 体重是double类型,强转可能精度缺失(-0.5会变为0)
* 所以使用Math.signum用来取差的符号
* static double signum(double d)
* 如果参数为零,则为零;如果参数大于零则为1.0;如果参数小于零,则为-1.0
* 获取符号后,我们可以进行强转,不会影响精度了
*/
@Override
public int compare(Person o1, Person o2) {
return (int) Math.signum(o1.weight-o2.weight);
}
}
/**
* 自定义类:人类(供测试用)
* @author Tian
*
*/
class Person{
String name;
int age;
double weight;
public Person(String name, int age, double weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", weight=" + weight + "]";
}
}
字符串提供比较大小的方法
int compareTo(String anotherString)
按字典顺序比较两个字符串(按照字符编码进行比较)
比较两个字符串时:
先比较前两个字符大小(第一个汉字),如果可以比较出来就返回,不行的话就比较第二个
返回0,表示相等;返回正数表示第一个字符串大;返回负数,表示第一个字符串小
先比较前两个字符大小(第一个汉字),如果可以比较出来就返回,不行的话就比较第二个
public static void main(String[] args) {
String s1 = "徐凤年";
String s2 = "邓太阿";
String s3 = "曹长卿";
int n = s1.compareTo(s2);
System.out.println(n);
}
使用比较器对名字列表进行排序
Collator.getInstance(java.util.Locale.CHINA)
这个方法是
Collator类调用了一下他的工厂方法(静态方法的一种常见用途)
该方法会返回一个比较器的对象,内部实现了按字符串首字符的拼音首字母排序
这个方法需要传入一个参数,语言包,我们这里传入的是中文
//按名字拼音的首字母排序
//创建了一个字符串的列表,用来接收人类中的姓名
List<String> str = new ArrayList<>();
//循环遍历人类列表,将姓名放到字符串列表中
for(Person p : list){
str.add(p.name);
}
//使用比较器对名字列表进行排序
/*
* Collator.getInstance(java.util.Locale.CHINA)
* 这个方法是
* Collator类调用了一下他的工厂方法(静态方法的一种常见用途)
* 该方法会返回一个比较器的对象,内部实现了按字符串首字符的拼音首字母排序
* 这个方法需要传入一个参数,语言包,我们这里传入的是中文
*/
Collections.sort(str,Collator.getInstance(java.util.Locale.CHINA));
//输出排序后的字符串列表
System.out.println(str);
//问题:只能修改String列表,怎么把这个修改顺序的影响扩大到Person列表中呢
静态方法的一种常见用途,用于构造对象
工厂方法的返回值为一个类的对象,用于使用一个类的静态方法完成创建一个我们需要的对象
比如上面的Collator.getInstance() 就是Collator中的静态方法,用来创建一个比较器对象