前言
在实际应用中,我们往往有需要 比较两个自定义对象 大小的地方。而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我们一般都是根据这些属性对自定义对象进行比较的。所以 Java 中要 比较对象的大小 或者要 对对象的集合 进行排序,需要通过比较这些对象的某些属性的大小来确定它们之间的大小关系
一般 Java 中通过接口来实现两个对象的比较,比较常用就是 Comparable 接口和Comparator 接口
Comparable 接口
Comparable 接口使用场景
- 一个类实现了
Comparable 接口,就意味着 该类支持排序 ,如果存在实现 Comparable 接口的类的 List 集合或 Array 数组,则该List 集合或 Array 数组可以通过 Collections.sort 或 Arrays.sort 来进行排序 - 一个类实现了
Comparable 接口,就意味着 该类支持两个对象比较大小
Comparable 接口源码
public interface Comparable<T> {
public int compareTo(T o);
}
Comparable 可以让实现它的类的对象进行比较,具体的比较规则是按照 compareT()o 方法中的规则进行的,该方法的返回值有三种情况e1.compareTo(e2) > 0 即 e1 > e2 e1.compareTo(e2) = 0 即 e1 = e2 e1.compareTo(e2) < 0 即 e1 < e2
实现 Comparable 接口示例
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ConsumInfo implements Comparable<ConsumInfo> {
private int uid;
private double price;
@Override
public int compareTo(@NotNull ConsumInfo o) {
if (price < o.price) {
return -1;
} else if (price > o.price) {
return 1;
} else {
return 0;
}
}
}
- 测试类:这里以对象的集合进行排序为例,当然也可以进行两个对象的大小比较
@Slf4j
public class ComparableTest {
public static void main(String[] args) {
ConsumInfo consumInfo1 = new ConsumInfo(100, 400.0);
ConsumInfo consumInfo2 = new ConsumInfo(200, 200.0);
ConsumInfo consumInfo3 = new ConsumInfo(300, 100.0);
ConsumInfo consumInfo4 = new ConsumInfo(400, 700.0);
ConsumInfo consumInfo5 = new ConsumInfo(500, 800.0);
ConsumInfo consumInfo6 = new ConsumInfo(600, 300.0);
ConsumInfo consumInfo7 = new ConsumInfo(700, 900.0);
ConsumInfo consumInfo8 = new ConsumInfo(800, 400.0);
List<ConsumInfo> list = new ArrayList<>();
list.add(consumInfo1);
list.add(consumInfo2);
list.add(consumInfo3);
list.add(consumInfo4);
list.add(consumInfo5);
list.add(consumInfo6);
list.add(consumInfo7);
list.add(consumInfo8);
log.info("排序前:------");
for (ConsumInfo consumInfo : list) {
log.info("consumInfo为:" + consumInfo);
}
Collections.sort(list);
log.info("排序后:------");
for (ConsumInfo consumInfo : list) {
log.info("consumInfo为:" + consumInfo);
}
}
}
00:16:09.316 [main] INFO org.example.test.ComparableTest - 排序前:------
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=100, price=400.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=200, price=200.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=300, price=100.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=400, price=700.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=500, price=800.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=600, price=300.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=700, price=900.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=800, price=400.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - 排序后:------
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=300, price=100.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=200, price=200.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=600, price=300.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=100, price=400.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=800, price=400.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=400, price=700.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=500, price=800.0)
00:16:09.332 [main] INFO org.example.test.ComparableTest - consumInfo为:ConsumInfo(uid=700, price=900.0)
Comparator 接口
Comparator 接口使用场景
- 如果需要对某个
类的集合进行排序 或 类对象比较大小 ,而该类本身又不能实现 Comparable 接口;那么,这时只需要实现 Comparator 接口即可
Comparator 接口源码
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
return thenComparing(comparing(keyExtractor, keyComparator));
}
default <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
{
return thenComparing(comparing(keyExtractor));
}
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparingInt(keyExtractor));
}
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
return thenComparing(comparingLong(keyExtractor));
}
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
return thenComparing(comparingDouble(keyExtractor));
}
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}
public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
}
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(true, comparator);
}
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(false, comparator);
}
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
}
public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
}
public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
}
}
实现 Comparator 接口示例
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ConsumInfo implements Comparable<ConsumInfo> {
private int uid;
private double price;
@Override
public int compareTo(@NotNull ConsumInfo o) {
if (price < o.price) {
return -1;
} else if (price > o.price) {
return 1;
} else {
return 0;
}
}
}
- 具体的比较类(比较器),实现
Comparator 接口
public class ComparatorConsumInfo implements Comparator<ConsumInfo> {
@Override
public int compare(ConsumInfo o1, ConsumInfo o2) {
if (o1.getPrice() > o2.getPrice()) {
return 1;
}
if (o1.getPrice() < o2.getPrice()) {
return -1;
}
if (o1.getPrice() == o2.getPrice()) {
if (o1.getUid() > o2.getUid()) {
return 1;
}
if (o1.getUid() < o2.getUid()) {
return -1;
}
}
return 0;
}
}
- 测试类:这里以对象的集合进行排序为例,当然也可以进行两个对象的大小比较
@Slf4j
public class ComparatorTest {
public static void main(String[] args) {
ConsumInfo consumInfo1 = new ConsumInfo(100, 400.0);
ConsumInfo consumInfo2 = new ConsumInfo(200, 200.0);
ConsumInfo consumInfo3 = new ConsumInfo(300, 100.0);
ConsumInfo consumInfo4 = new ConsumInfo(400, 700.0);
ConsumInfo consumInfo5 = new ConsumInfo(500, 800.0);
ConsumInfo consumInfo6 = new ConsumInfo(600, 300.0);
ConsumInfo consumInfo7 = new ConsumInfo(700, 900.0);
ConsumInfo consumInfo8 = new ConsumInfo(800, 400.0);
List<ConsumInfo> list = new ArrayList<>();
list.add(consumInfo1);
list.add(consumInfo2);
list.add(consumInfo3);
list.add(consumInfo4);
list.add(consumInfo5);
list.add(consumInfo6);
list.add(consumInfo7);
list.add(consumInfo8);
log.info("排序前:------");
for (ConsumInfo consumInfo : list) {
log.info("consumInfo为:" + consumInfo);
}
ComparatorConsumInfo comparatorConsumInfo = new ComparatorConsumInfo();
Collections.sort(list, comparatorConsumInfo);
log.info("排序后:------");
for (ConsumInfo consumInfo : list) {
log.info("consumInfo为:" + consumInfo);
}
}
}
Comparable 接口与 Comparator 接口对比
Comparable 接口
Comparable 位于包 java.lang 下Comparable 接口将比较代码嵌入需要进行比较的类的自身中Comparable 接口强制进行自然排序
Comparator 接口
Comparator 位于包 java.util 下Comparator 接口在一个独立的类中实现比较,排序- 如果前期没有实现
Comparable 接口,后期可以通过 Comparator 接口来实现比较算法进行排序 Comparator 接口不强制进行自然排序,可以指定排序顺序,比如:升序、降序
|