排序
简介
排序相关的接口有2个:
-
Comparator: 主要需要实现的方法是
compare(T o1, T o2)
.该方法的返回值是1,0和-1.实现该接口的类是一个比较器,可以比较其它类的2个不同实例.换言之,它处理的是和自己不相关的2个对象.注意:返回负值代表o1排在前面(即o1-o2<0),返回正值代表o1排在后面(即o1-o2>0) -
Comparable: 主要需要实现的方法是
compareTo(T o)
.该方法的返回值是1,0和-1.实现该接口的类,它的实例之间可以相互比较.换言之,实现该接口可以让自己和其它对象比较.实现这个接口的排序也叫自然排序(natural ordering),相对来说Comparator实现的是自定义排序.
这2个接口都让需要排序的类的实例具备可比较排序的能力,它们的区别是Comparable是一个类与生俱来的内在的默认的排序规则,比如代表一个人的类,根据年龄排序.但是如果还需要其它的更多的排序规则,比如根据成绩,根据身高等排序,就需要借助Comparator实现更多的排序规则,一个规则对应一个实现了Comparator接口的类.
注意: 如果一个类实现了Comparable,但是比较的时候又使用了Comparator,比较的规则要按照Comparator中的规则来,Comparable对应的自然排序规则完全不起作用.
返回值和排序的关系
返回值可以不是-1和1,但是必须是2个符号相反的整数,比如-2、0、2的组合也是可以的,其它以此类推.返回负值代表排序在前面,返回正值代表排序在后面
排序触发
是不是具备了排序的能力就会自动排序呢?不是的.需要调用排序相关的方法触发排序.主要的方法是:
-
Collections.sort(): 用于对java.util.List排序,具体参数是
sort(List<T> list)
或者sort(List<T> list, Comparator<? super T> c)
. -
Arrays.sort(): 用于数组的排序
代码案例
使用Arrays.sort对int[]排序
代码如下:
@Test
public void sortInt() {
int[] intArray = {2,3,4,1,0,9,8};
for (int i=0; i<intArray.length; i++) {
System.out.println("原始数组:"+i+"-"+intArray[i]);
}
System.out.println("===============");
Arrays.sort(intArray);
for (int i=0; i<intArray.length; i++) {
System.out.println("排序后的数组:"+i+"-"+intArray[i]);
}
}
执行测试打印结果如下:
原始数组:0-2
原始数组:1-3
原始数组:2-4
原始数组:3-1
原始数组:4-0
原始数组:5-9
原始数组:6-8
===============
排序后的数组:0-0
排序后的数组:1-1
排序后的数组:2-2
排序后的数组:3-3
排序后的数组:4-4
排序后的数组:5-8
排序后的数组:6-9
可以int[]使用Arrays.sort(int[] a)
排序是按照由小到大排序的.如果需要自定义排序,可以实现Comparator接口并使用Arrays.sort(T[] a, Comparator<? super T> c)
方法排序.
使用Collections.sort对List进行自然排序(natural ordering)
商品有价格、编号、销量、名称4个属性,商品的自然排序(natural ordering)是按价格由高到低.对应的商品类为:
package com.ms.util.sort.list;
/**
* 商品的自然排序(Natural Ordering)是按价格由大到小
* 自然排序也就是实现了Comparable接口的排序
* @author iengchen
* @since 2018-05-01
*/
public class ProductSort implements Comparable<ProductSort> {
//价格
private int price;
//销量
private int soldNum;
//分类编号
private int proNum;
//名称
private String name;
public ProductSort(int price,int soldNum,int proNum,String name) {
this.price = price;
this.soldNum = soldNum;
this.proNum = proNum;
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getSoldNum() {
return soldNum;
}
public void setSoldNum(int soldNum) {
this.soldNum = soldNum;
}
public int getProNum() {
return proNum;
}
public void setProNum(int proNum) {
this.proNum = proNum;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int compareTo(ProductSort o) {
if (this.price > o.price) {
//返回负值代表排在被比较的对象的前面,这里是价格大的排前面
return -1;
} else if (this.price < o.price) {
return 1;
} else {
return 0;
}
}
}
测试类ProductSortTest.java为
package com.ms.util.sort.list;
import java.util.ArrayList;
import java.util.Collections;
import org.junit.Test;
/**
* 对ProductSort类测试
* @author iengchen
* @since 2018-05-01
*/
public class ProductSortTest {
/**
* 测试自然排序,也就是Comparable接口的compareTo方法所实现的排序规则.
* @author iengchen
* @since 2018-05-01
*/
@Test
public void naturalOrderingTest() {
ProductSort ps1 = new ProductSort(23, 322, 3, "松下电视机");
ProductSort ps2 = new ProductSort(74, 99, 3, "索尼电视机");
ProductSort ps3 = new ProductSort(3, 488, 8, "卫龙辣条");
ProductSort ps4 = new ProductSort(18, 300, 4, "美的电吹风");
ArrayList<ProductSort> productSorts = new ArrayList<>();
productSorts.add(ps1);
productSorts.add(ps2);
productSorts.add(ps3);
productSorts.add(ps4);
for (int i = 0; i < productSorts.size(); i++) {
ProductSort ps = productSorts.get(i);
System.out.println("名称:"+ps.getName()+",商品分类:"+ps.getProNum()+",销量:"+ps.getSoldNum()+",价格:"+ps.getPrice());
}
System.out.println("====== 自然排序后 ======");
Collections.sort(productSorts);
for (int i = 0; i < productSorts.size(); i++) {
ProductSort ps = productSorts.get(i);
System.out.println("名称:"+ps.getName()+",商品分类:"+ps.getProNum()+",销量:"+ps.getSoldNum()+",价格:"+ps.getPrice());
}
}
}
执行测试方法打印结果如下:
名称:松下电视机,商品分类:3,销量:322,价格:23
名称:索尼电视机,商品分类:3,销量:99,价格:74
名称:卫龙辣条,商品分类:8,销量:488,价格:3
名称:美的电吹风,商品分类:4,销量:300,价格:18
====== 自然排序后 ======
名称:索尼电视机,商品分类:3,销量:99,价格:74
名称:松下电视机,商品分类:3,销量:322,价格:23
名称:美的电吹风,商品分类:4,销量:300,价格:18
名称:卫龙辣条,商品分类:8,销量:488,价格:3
使用Collections.sort对List进行自定义排序
在上面的测试类ProductSortTest.java中添加下面的代码:
/**
* 使用Comparator实现自定义排序,按销量由高到低
* @author iengchen
* @since 2018-05-01
*/
@Test
public void customOrderTest() {
ProductSort ps1 = new ProductSort(23, 322, 3, "松下电视机");
ProductSort ps2 = new ProductSort(74, 99, 3, "索尼电视机");
ProductSort ps3 = new ProductSort(3, 488, 8, "卫龙辣条");
ProductSort ps4 = new ProductSort(18, 300, 4, "美的电吹风");
ArrayList<ProductSort> productSorts = new ArrayList<>();
productSorts.add(ps1);
productSorts.add(ps2);
productSorts.add(ps3);
productSorts.add(ps4);
for (int i = 0; i < productSorts.size(); i++) {
ProductSort ps = productSorts.get(i);
System.out.println("名称:"+ps.getName()+",商品分类:"+ps.getProNum()+",销量:"+ps.getSoldNum()+",价格:"+ps.getPrice());
}
System.out.println("====== 自定义排序后 ======");
Collections.sort(productSorts, new Comparator<ProductSort>() {
//compare方法返回值为正代表o1-o2>0,即o1>o2。
//返回值为负代表o1-o2<0,即o1<o2。
@Override
public int compare(ProductSort o1, ProductSort o2) {
if (o1.getSoldNum() > o2.getSoldNum()) {
//-1表示o1<o2,o2排在后面。注意:返回值和if中的大小没有关系,只和传递进来的参数顺序有关。
return -1;
} else if (o1.getSoldNum() < o2.getSoldNum()) {
//返回1表示o1>o2,o1排在后面。注意:返回值和if中的大小没有关系,只和传递进来的参数顺序有关。
return 1;
} else {
return 0;
}
}
});
for (int i = 0; i < productSorts.size(); i++) {
ProductSort ps = productSorts.get(i);
System.out.println("名称:"+ps.getName()+",商品分类:"+ps.getProNum()+",销量:"+ps.getSoldNum()+",价格:"+ps.getPrice());
}
}
执行这个测试方法的打印结果如下:
名称:松下电视机,商品分类:3,销量:322,价格:23
名称:索尼电视机,商品分类:3,销量:99,价格:74
名称:卫龙辣条,商品分类:8,销量:488,价格:3
名称:美的电吹风,商品分类:4,销量:300,价格:18
====== 自定义排序后 ======
名称:卫龙辣条,商品分类:8,销量:488,价格:3
名称:松下电视机,商品分类:3,销量:322,价格:23
名称:美的电吹风,商品分类:4,销量:300,价格:18
名称:索尼电视机,商品分类:3,销量:99,价格:74
可以看到按照销量由高到低排序.自然排序规则没有起作用.可以看出,当使用了Comparator时,Comparable的排序规则会失效.
网友评论