在实际应用中,我们往往有需要 比较两个自定义对象
大小的地方。而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我们一般都是根据这些属性对自定义对象进行比较的。所以 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) {
// 首先比较price,如果price相同,则比较uid
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) {
// 首先比较price,如果price相同,则比较uid
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
接口不强制进行自然排序,可以指定排序顺序,比如:升序、降序