在排序任务中,可将其分为自然排序:数值大小、字符Asics码序列的排序;客户化排序:也即通过自定义的序列方式进行排序。
在JDK类库中,有一部分类实现了Comparable接口,如Integer Double和String等,如下Integer类实现了Comparable的接口,通过重写compareTo方法定义了排序的规则:
返回值 | 含义 |
---|---|
-1 | 大于 |
0 | 等于 |
1 | 小于 |
//Integer类中部分源码;实现了Comparable的接口,可以进行自然排序
public final class Integer extends Number implements Comparable<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);
}
}
JDK中实现了Comparable接口的类库
类名 | 排序方式 |
---|---|
BigDecimal BigInteger Byte Double Float Integer Long Short | 按数字大小排序 |
Character | 按字符的Unicode值的数字大小排序 |
String | 按字符中字符的Unicode值排序 |
注意:使用自然排序时只能向集合中加入同类型的对象,并且这些对象的类必须实现Comparable接口 。
对自己定义的类,设置规则实现排序。如:对学生信息先按照学号升序,再按照成绩降序排列;
创建学生类:
public class A04_Comparable_Student implements Comparable<A04_Comparable_Student> {
private String name;
private int id;
private float score;
public A04_Comparable_Student(String name, int id, float score) {
// TODO Auto-generated constructor stub
this.name = name;
this.id = id;
this.score = score;
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the score
*/
public float getScore() {
return score;
}
/**
* @param score the score to set
*/
public void setScore(float score) {
this.score = score;
}
@Override
public int compareTo(A04_Comparable_Student stu) {
// TODO Auto-generated method stub
if (this.id > stu.id) {
return 1;
}else if (this.id < stu.id) {
return -1;
}else {
if (this.score > stu.score) {
return =1;
}else if (this.score < stu.score) {
return 1;
}else {
return 0;
}
}
}
@Override
public String toString() {
return "A04_Comparable_Student [name=" + name + ", id=" + id + ", score=" + score + "]";
}
}
初始化学生类并执行排序:
import java.util.Arrays;
public class A04_Comparable_Caller {
public static void main(String[] args) {
A04_Comparable_Student stu[] = {
new A04_Comparable_Student("张三",20,100f)
,new A04_Comparable_Student("李四",29,70f)
,new A04_Comparable_Student("王五",12,80f)
,new A04_Comparable_Student("王五",12,113f)
,new A04_Comparable_Student("李四",29,80f)};
Arrays.sort(stu);
for (int i = 0; i < stu.length; i++) {
System.out.println(stu[i].toString());
}
}
}
执行结果:
A04_Comparable_Student [name=王五, id=12, score=113.0]
A04_Comparable_Student [name=王五, id=12, score=80.0]
A04_Comparable_Student [name=张三, id=20, score=100.0]
A04_Comparable_Student [name=李四, id=29, score=80.0]
A04_Comparable_Student [name=李四, id=29, score=70.0]
如果一个类已经开放完成,但是在此类建立的初期并没有实现Comparable接口,无法进行对象排序操作的,所以为了解决这一的问题,Java又定义了另一个比较器的操作接口 Comparator 。
定义Comparator:
import java.util.Comparator;
public class A04_MyComparator implements Comparator<A04_Comparable_Student>{
@Override
public int compare(A04_Comparable_Student stu1, A04_Comparable_Student stu2) {
// TODO Auto-generated method stub
if (stu2.getId() > stu1.getId()) {
return 1;
}else if (stu2.getId() < stu1.getId()) {
return -1;
}else {
if (stu2.getScore()> stu1.getScore()) {
return -1;
}else if (stu2.getScore()< stu1.getScore()) {
return 1;
}else {
return 0;
}
}
}
}
使用Comparator:
import java.util.Arrays;
public class A04_MyComparator_Caller {
public static void main(String[] args) {
A04_Comparable_Student stu[] = {
new A04_Comparable_Student("张三",20,100f)
,new A04_Comparable_Student("李四",29,70f)
,new A04_Comparable_Student("王五",12,80f)
,new A04_Comparable_Student("王五",12,113f)
,new A04_Comparable_Student("李四",29,80f)};
Arrays.sort(stu,new A04_MyComparator());
for (int i = 0; i < stu.length; i++) {
System.out.println(stu[i].toString());
}
}
}
执行结果为:
A04_Comparable_Student [name=李四, id=29, score=70.0]
A04_Comparable_Student [name=李四, id=29, score=80.0]
A04_Comparable_Student [name=张三, id=20, score=100.0]
A04_Comparable_Student [name=王五, id=12, score=80.0]
A04_Comparable_Student [name=王五, id=12, score=113.0]
Comparable与Comparator的排序操作就是二叉树排序算法:
二叉树排序的基本原理:使用第一个元素作为根节点,之后如果后面的内容比根节点小,则放在左子树,如果内容比根节点的内容要大,则放在右子树。
//Arrays中Comparable排序的源码
private static void binarySort(Object[] a, int lo, int hi, int start) {
assert lo <= start && start <= hi;
if (start == lo)
start++;
for ( ; start < hi; start++) {
Comparable pivot = (Comparable) a[start];
// Set left (and right) to the index where a[start] (pivot) belongs
int left = lo;
int right = start;
assert left <= right;
/*
* Invariants:
* pivot >= all in [lo, left).
* pivot < all in [right, start).
*/
while (left < right) {
int mid = (left + right) >>> 1;
if (pivot.compareTo(a[mid]) < 0)
right = mid;
else
left = mid + 1;
}
assert left == right;
int n = start - left; // The number of elements to move
// Switch is just an optimization for arraycopy in default case
switch (n) {
case 2: a[left + 2] = a[left + 1];
case 1: a[left + 1] = a[left];
break;
default: System.arraycopy(a, left, a, left + 1, n);
}
a[left] = pivot;
}
}
Comparable & Comparator都是用来实现集合中元素的比较、排序的, Comparator位于包java.util下,是在集合内部定义的方法实现的排序,Comparable位于包java.lang下, 是在集合外部实现的排序。
引用:
https://www.cnblogs.com/z2002m/archive/2011/10/24/2222780.html
https://www.jianshu.com/p/81e5c3e88fc6