1.
两种比较接口分析
在
“
集合框架
”
中有两种比较接口:
Comparable
接口和
Comparator
接口。
Comparable
是通用的接口,用户可以实现它来完成自己特定的比较,而
Comparator
可以看成一种算法的实现,在需要容器集合实现比较功能的时候,来指定这个比较器,这可以看成一种设计模式,将算法和数据分离。
前者应该比较固定,和一个具体类相绑定,而后者比较灵活,它可以被用于各个需要比较功能的类使用。
一个类实现了
Camparable
接口表明这个类的对象之间是可以相互比较的。如果用数学语言描述的话就是这个类的对象组成的集合中存在一个全序。这样,这个类对象组成的集合就可以使用
Sort
方法排序了。
而
Comparator
的作用有两个:
1
、如果类的设计师没有考虑到
Compare
的问题而没有实现
Comparable
接口,可以通过
Comparator
来实现比较算法进行排序;
2
、为了使用不同的排序标准做准备,比如:升序、降序或其他什么序。
2 Comparable
接口
public
interface
Comparable
public
int
compareTo(T o);
}
|
java.lang. Comparable
接口定义类的自然顺序,实现该接口的类就可以按这种方式排序。
1
)
int compareTo(Object o):
比较当前实例对象与对象
o
,如果位于对象
o
之前,返回负值,如果两个对象在排序中位置相同,则返回
0
,如果位于对象
o
后面,则返回正值。
2
)在
Java 2 SDK
版本
1.4
中有二十四个类实现
Comparable
接口。下表展示了
8
种基本类型的自然排序。虽然一些类共享同一种自然排序,但只有相互可比的类才能排序。
类
|
排序
|
BigDecimal,BigInteger,Byte,Double, Float,Integer,Long,Short
|
按数字大小排序
|
Character
|
按
Unicode
值的数字大小排序
|
String
|
按字符串中字符
Unicode
值排序
|
利用
Comparable
接口创建自己的类的排序顺序,只是实现
compareTo()
方法的问题。通常就是依赖几个数据成员的自然排序。同时类也应该覆盖
equals()
和
hashCode()
以确保两个相等的对象返回同一个哈希码。
这个接口的作用:如果数组或者集合中的(类)元素实现了该接口的话
,
我们就可以调用
Collections.sort
和
Arrays.sort
排序,或应用于有序集合
TreeSet
和
TreeMap
中。
下面设计一个有序的类
Person
,它实现
Comparable
接口,以年龄为第一关键字,姓名为第二关键字升序排序。
Person.java
package
com.zj.sort.comparable;
public
class
Person
implements
Comparable
private
int
age
;
private
String
name
;
public
Person(
int
age, String name) {
this
.
age
= age;
this
.
name
= name;
}
public
int
compareTo(Person person) {
int
cop =
age
- person.getAge();
if
(cop != 0)
return
cop;
else
return
name
.compareTo(person.
name
);
}
public
int
getAge() {
return
age
;
}
public
String getName() {
return
name
;
}
public
int
hashCode() {
int
result = 17;
result = 37 * result +
age
;
result = 37 * result +
name
.hashCode();
return
result;
}
public
boolean
equals(Object o) {
if
(!(o
instanceof
Person))
return
false
;
Person person = (Person) o;
return
(
age
== person.
age
) && (
name
.equals(person.
name
));
}
public
String toString() {
return
(
age
+
"{"
+
name
+
"}"
);
}
}
|
2.1
测试
Arrays.sort
()方法
ArraysSortUnit.java
package
com.zj.sort.comparable;
import
java.util.Arrays;
import
com.zj.compare.Person;
public
class
ArraysSortUnit {
public
static
void
main(String[] args) {
Person[] ps = {
new
Person(20,
"Tom"
),
new
Person(20,
"Jeff"
),
new
Person(30,
"Mary"
),
new
Person(20,
" Ada "
),
new
Person(40,
"Walton"
),
new
Person(61,
"Peter"
),
new
Person(20,
"Bush"
) };
System.
out
.println(Arrays.toString(ps));
Arrays.sort(ps);
System.
out
.println(Arrays.toString(ps));
}
}
|
结果:
[20{Tom}, 20{Jeff}, 30{Mary}, 20{ Ada }, 40{Walton}, 61{Peter}, 20{Bush}]
[20{ Ada }, 20{Bush}, 20{Jeff}, 20{Tom}, 30{Mary}, 40{Walton}, 61{Peter}]
2.2
测试
Collections.sort
()方法
CollctionsSortUnit.java
package
com.zj.sort.comparable;
import
java.util.Arrays;
import
java.util.Collections;
import
com.zj.compare.Person;
public
class
CollctionsSortUnit {
public
static
void
main(String[] args) {
Person[] ps = {
new
Person(20,
"Tom"
),
new
Person(20,
"Jeff"
),
new
Person(30,
"Mary"
),
new
Person(20,
" Ada "
),
new
Person(40,
"Walton"
),
new
Person(61,
"Peter"
),
new
Person(20,
"Bush"
) };
System.
out
.println(Arrays.toString(ps));
Collections.sort(Arrays.asList(ps));
System.
out
.println(Arrays.toString(ps));
}
}
|
结果:
[20{Tom}, 20{Jeff}, 30{Mary}, 20{ Ada }, 40{Walton}, 61{Peter}, 20{Bush}]
[20{ Ada }, 20{Bush}, 20{Jeff}, 20{Tom}, 30{Mary}, 40{Walton}, 61{Peter}]
2.3
测试
TreeSet
TreeSetUnit.java
package
com.zj.sort.comparable;
import
java.util.TreeSet;
import
com.zj.compare.Person;
public
class
TreeSetUnit {
public
static
void
main(String[] args) {
TreeSet
set.add(
new
Person(20,
"Tom"
));
set.add(
new
Person(20,
"Jeff"
));
set.add(
new
Person(30,
"Mary"
));
set.add(
new
Person(20,
" Ada "
));
set.add(
new
Person(40,
"Walton"
));
set.add(
new
Person(61,
"Peter"
));
set.add(
new
Person(20,
"Bush"
));
System.
out
.println(set);
}
}
|
结果:
[20{ Ada }, 20{Bush}, 20{Jeff}, 20{Tom}, 30{Mary}, 40{Walton}, 61{Peter}]
2.4
测试
TreeMap
TreeMapUnit.java
package
com.zj.sort.comparable;
import
java.util.TreeMap;
import
com.zj.compare.Person;
public
class
TreeMapUnit {
public
static
void
main(String[] args) {
TreeMap
map.put(
new
Person(20,
"Tom"
),
"Tom"
);
map.put(
new
Person(20,
"Jeff"
),
"Jeff"
);
map.put(
new
Person(30,
"Mary"
),
"Mary"
);
map.put(
new
Person(20,
" Ada "
),
" Ada "
);
map.put(
new
Person(40,
"Walton"
),
"Walton"
);
map.put(
new
Person(61,
"Peter"
),
"Peter"
);
map.put(
new
Person(20,
"Bush"
),
"Bush"
);
System.
out
.println(map);
}
}
|
结果:
{20{ Ada }= Ada , 20{Bush}=Bush, 20{Jeff}=Jeff, 20{Tom}=Tom, 30{Mary}=Mary, 40{Walton}=Walton, 61{Peter}=Peter}
3. Comparator
接口
public
interface
Comparator
int
compare(T o1, T o2);
boolean
equals(Object obj);
}
|
若一个类不能用于实现
java.lang.Comparable
,或者不喜欢缺省的
Comparable
行为并想提供自己的排序顺序
(
可能多种排序方式
)
,你可以实现
Comparator
接口,从而定义一个比较器。
1
)
int compare(Object o1, Object o2):
对两个对象
o1
和
o2
进行比较,如果
o1
位于
o2
的前面,则返回负值,如果在排序顺序中认为
o1
和
o2
是相同的,返回
0
,如果
o1
位于
o2
的后面,则返回正值。
2
)与
Comparable
相似,
0
返回值不表示元素相等。一个
0
返回值只是表示两个对象排在同一位置。由
Comparator
用户决定如何处理。
3
)
boolean equals(Object obj):
指示对象
obj
是否和比较器相等。该方法覆写
Object
的
equals()
方法,检查的是
Comparator
实现的等同性,不是处于比较状态下的对象。
下面设计一个定义完整
equals
方法和
hashCode
方法的类
Person
。
Person.java
package
com.zj.sort.comparator;
public
class
Person {
private
String
firstName
;
private
String
lastName
;
private
int
age
;
public
Person(
int
age, String firstName, String lastName) {
this
.
age
= age;
this
.
firstName
= firstName;
this
.
lastName
= lastName;
}
public
int
getAge() {
return
age
;
}
public
String getFirstName() {
return
firstName
;
}
public
String getLastName() {
return
lastName
;
}
public
int
hashCode() {
int
result = 17;
result = 37 * result +
age
;
result = 37 * result +
firstName
.hashCode();
result = 37 * result +
lastName
.hashCode();
return
result;
}
public
boolean
equals(Object o) {
if
(!(o
instanceof
Person))
return
false
;
Person p = (Person) o;
return
(
age
== p.
age
) && (
firstName
.equals(p.
firstName
))
&& (
lastName
.equals(p.
lastName
));
}
public
String toString() {
return
(
age
+
"{"
+
firstName
+
" "
+
lastName
+
"}"
);
}
}
|
下面设计两个比较器。
FirstNameComparator.java
package
com.zj.sort.comparator;
import
java.util.Comparator;
//
实现按
FirstName
优先排序
public
class
FirstNameComparator
implements
Comparator
public
int
compare(Person person, Person anotherPerson) {
String lastName1 = person.getLastName().toUpperCase();
String firstName1 = person.getFirstName().toUpperCase();
String lastName2 = anotherPerson.getLastName().toUpperCase();
String firstName2 = anotherPerson.getFirstName().toUpperCase();
if
(firstName1.equals(firstName2))
return
lastName1.compareTo(lastName2);
else
return
firstName1.compareTo(firstName2);
}
}
|
LastNameComparator.java
package
com.zj.sort.comparator;
import
java.util.Comparator;
//
实现按
LastName
优先排序
public
class
LastNameComparator
implements
Comparator
public
int
compare(Person person, Person anotherPerson) {
String lastName1 = person.getLastName().toUpperCase();
String firstName1 = person.getFirstName().toUpperCase();
String lastName2 = anotherPerson.getLastName().toUpperCase();
String firstName2 = anotherPerson.getFirstName().toUpperCase();
if
(lastName1.equals(lastName2))
return
firstName1.compareTo(firstName2);
else
return
lastName1.compareTo(lastName2);
}
}
|
下面通过上述两个比较器,调用
Collections.sort
和
Arrays.sort
排序,以及将其应用于有序集合
TreeSet
和
TreeMap
中。
3.1
测试
Arrays.sort
()方法
ArraysSortUnit.java
package
com.zj.sort.comparator;
import
java.util.Arrays;
public
class
ArraysSortUnit {
public
static
void
main(String[] args) {
Person[] ps = {
new
Person(20,
"Tom"
,
"A"
),
new
Person(20,
"Jeff"
,
"A"
),
new
Person(30,
"Mary"
,
"A"
),
new
Person(20,
" Ada "
,
"B"
),
new
Person(40,
"Walton"
,
"B"
),
new
Person(61,
"Peter"
,
"B"
),
new
Person(20,
"Bush"
,
"B"
) };
System.
out
.println(Arrays.toString(ps));
Arrays.sort(ps,
new
FirstNameComparator());
System.
out
.println(Arrays.toString(ps));
Arrays.sort(ps,
new
LastNameComparator());
System.
out
.println(Arrays.toString(ps));
}
}
|
结果:
[20{Tom A}, 20{Jeff A}, 30{Mary A}, 20{ Ada B}, 40{Walton B}, 61{Peter B}, 20{Bush B}]
[20{ Ada B}, 20{Bush B}, 20{Jeff A}, 30{Mary A}, 61{Peter B}, 20{Tom A}, 40{Walton B}]
[20{Jeff A}, 30{Mary A}, 20{Tom A}, 20{ Ada B}, 20{Bush B}, 61{Peter B}, 40{Walton B}]
3.2
测试
Collections.sort
()方法
CollctionsSortUnit.java
package
com.zj.sort.comparator;
import
java.util.Arrays;
import
java.util.Collections;
public
class
CollectionsSortUnit {
public
static
void
main(String[] args) {
Person[] ps = {
new
Person(20,
"Tom"
,
"A"
),
new
Person(20,
"Jeff"
,
"A"
),
new
Person(30,
"Mary"
,
"A"
),
new
Person(20,
" Ada "
,
"B"
),
new
Person(40,
"Walton"
,
"B"
),
new
Person(61,
"Peter"
,
"B"
),
new
Person(20,
"Bush"
,
"B"
) };
System.
out
.println(Arrays.toString(ps));
Collections.sort(Arrays.asList(ps),
new
FirstNameComparator());
System.
out
.println(Arrays.toString(ps));
Collections.sort(Arrays.asList(ps),
new
LastNameComparator());
System.
out
.println(Arrays.toString(ps));
}
}
|
结果:
[20{Tom A}, 20{Jeff A}, 30{Mary A}, 20{ Ada B}, 40{Walton B}, 61{Peter B}, 20{Bush B}]
[20{ Ada B}, 20{Bush B}, 20{Jeff A}, 30{Mary A}, 61{Peter B}, 20{Tom A}, 40{Walton B}]
[20{Jeff A}, 30{Mary A}, 20{Tom A}, 20{ Ada B}, 20{Bush B}, 61{Peter B}, 40{Walton B}]
3.3
测试
TreeSet
TreeSetUnit.java
package
com.zj.sort.comparator;
import
java.util.TreeSet;
public
class
TreeSetUnit {
public
static
void
main(String[] args) {
TreeSet
new
FirstNameComparator());
firstNameSet.add(
new
Person(20,
"Tom"
,
"A"
));
firstNameSet.add(
new
Person(20,
"Jeff"
,
"A"
));
firstNameSet.add(
new
Person(30,
"Mary"
,
"A"
));
firstNameSet.add(
new
Person(20,
" Ada "
,
"B"
));
firstNameSet.add(
new
Person(40,
"Walton"
,
"B"
));
firstNameSet.add(
new
Person(61,
"Peter"
,
"B"
));
firstNameSet.add(
new
Person(20,
"Bush"
,
"B"
));
System.
out
.println(firstNameSet);
TreeSet
new
LastNameComparator());
lastNameSet.addAll(firstNameSet);
System.
out
.println(lastNameSet);
}
}
|
结果:
[20{ Ada B}, 20{Bush B}, 20{Jeff A}, 30{Mary A}, 61{Peter B}, 20{Tom A}, 40{Walton B}]
[20{Jeff A}, 30{Mary A}, 20{Tom A}, 20{ Ada B}, 20{Bush B}, 61{Peter B}, 40{Walton B}]
3.4
测试
TreeMap
TreeMapUnit.java
package
com.zj.sort.comparator;
import
java.util.TreeMap;
public
class
TreeMapUnit {
public
static
void
main(String[] args) {
TreeMap
new
FirstNameComparator());
firstNameMap.put(
new
Person(20,
"Tom"
,
"A"
),
"Tom A"
);
firstNameMap.put(
new
Person(20,
"Jeff"
,
"A"
),
"Jeff A"
);
firstNameMap.put(
new
Person(30,
"Mary"
,
"A"
),
"Mary A"
);
firstNameMap.put(
new
Person(20,
" Ada "
,
"B"
),
"Ada B"
);
firstNameMap.put(
new
Person(40,
"Walton"
,
"B"
),
"Walton B"
);
firstNameMap.put(
new
Person(61,
"Peter"
,
"B"
),
"Peter B"
);
firstNameMap.put(
new
Person(20,
"Bush"
,
"B"
),
"Bush B"
);
System.
out
.println(firstNameMap);
TreeMap
new
LastNameComparator());
lastNameMap.putAll(firstNameMap);
System.
out
.println(lastNameMap);
}
}
|
结果:
{20{ Ada B}= Ada B, 20{Bush B}=Bush B, 20{Jeff A}=Jeff A, 30{Mary A}=Mary A, 61{Peter B}=Peter B, 20{Tom A}=Tom A, 40{Walton B}=Walton B}
{20{Jeff A}=Jeff A, 30{Mary A}=Mary A, 20{Tom A}=Tom A, 20{ Ada B}= Ada B, 20{Bush B}=Bush B, 61{Peter B}=Peter B, 40{Walton B}=Walton B}