Comparator比较器

简介

为什么写?


  • comparatorjavase中的接口,位于java.util包下,该接口抽象度极高,有必要掌握该接口的使用
  • 大多数文章告诉大家comparator是用来排序,但我想说排序是comparator能实现的功能之一,他不仅限于排序

接口功能


Comparator接口代表一个比较器,比较器具有可比性!平时我们大多数都是使用改接口(Comparator)实现对集合,排序。这是

因为JAVASE数组工具类和集合工具类中提供的sort方法sort就是使用Comparator接口来处理排序的,但是Comparator接口并不只是

用来排序的,下面是JAVASE一些使用到Comparator接口的地方:

Arrays.sort(T[],Comparator<? super T> c);
Collections.sort(List<T> list,Comparator<? super T> c);

使用场景


什么场景需要做比较,那么什么场景就是Comparator接口的用武之地,我总结的两个场景:

  1. 排序,需要比较两个对象谁排在前谁排在后(排序也可以让类实现Comparable接口,实现后该类的实例也具有排序能力)。
  2. 分组,需要比较两个对象是否是属于同一组。

排序场景

在List或数组中的对象如果没有实现Comparable接口时,那么就需要调用者为需要排序的数组或List设置一个Compartor,Compartor的compare方法用来告诉代码应该怎么去比较两个实例,然后根据比较结果进行排序。

条件排序:公共代码

public class SortTest {

    @Data
@AllArgsConstructor
@ToString
class Dog{ //内部类
public int age;
public String name;
public String num;
} List<Dog> list= new ArrayList<Dog>(){
{
add(new Dog(5, "DogA","001"));
add(new Dog(5, "DogB","002"));
add(new Dog(5, "DogC","003"));
add(new Dog(9, "DogA","004"));
add(new Dog(35, "DogF","005"));
add(new Dog(74, "Dogg","006"));
}
};
}

单一条件排序

Comparator实现排序(按照年龄,名字)

   /**
*单一条件排序
*/ @Test
public void test1(){
//按照年龄排序
Collections.sort(list, new Comparator<Dog>() {
//实现compare(T o1, To2) 方法,返回正数,零,负数各代表大于,等于小于
@Override
public int compare(Dog o1, Dog o2) {
//return o2.age - o1.age; //排序规则----升序
return String.valueOf(o1.getAge()).compareTo(String.valueOf(o2.getAge())); //compareTo()传String
}
});
System.out.println("给狗狗按照年龄倒序:"+list);
} @Test
public void test2(){
//按照名字排序
Collator comparator = Collator.getInstance(Locale.CANADA); Collections.sort(list, new Comparator<Dog>() { @Override
public int compare(Dog o1, Dog o2) {
// return o1.name.compareTo(o2.name);
return comparator.compare(o1.getName(),o2.getName());
}
});
System.out.println("给狗狗按名字字母顺序排序:"+list);
}

Lambda优化实现排序

    /**
*使用Lambda表达式优化比较器代码(单一条件排序)
*/
@Test
public void test3() {
//对学生集合按年龄进行排序
Collections.sort(list,(s1, s2) -> (s1.getAge() - s2.getAge()) );
}

多条件排序

Comparator实现排序(按照年龄和名字)

 	/**
*多条件排序
*/
@Test
public void test4() { Collections.sort(list,new Comparator<Dog>() { @Override
public int compare(Dog s1, Dog s2) {
int flag;
// 首选按年龄升序排序
flag = s1.getAge()-s2.getAge();
if(flag==0){
// 如果年龄按编号降序排序
flag = s2.getNum().compareTo(s1.getNum());
}
return flag;
}
});
list.forEach(System.out::println);
}

Lambda优化实现多条件排序

       /**
*多条件排序 ----使用lambda表达式优化
*/
@Test
public void test5() {
Collections.sort(list,(s1,s2)->{
int flag;
// 首选按年龄升序排序
flag = s1.getAge()-s2.getAge(); // 方案一、判断是否为空 --- 为空执行lambda表达式,返回一个对象
flag = Optional.ofNullable(flag == 0 ? null: flag).orElseGet(() -> s2.getNum().compareTo(s1.getNum())); //方案二、
if(flag==0){
// 如果年龄按编号降序排序
flag =s2.getNum().compareTo(s1.getNum());
}
//最终返回
return flag;
});
list.forEach(System.out::println);
}

自定义条件排序

自定义条件排序公共代码


    /**
*自定义条件排序
*/
//定义排序规则 通过asList()方法将数组转为list集合
String[] order = {"语文","数学","英语","物理","化学","生物","政治","历史","地理","总分"};
final List<String> definedOrder = Arrays.asList(order); //需要排序的数据
List<String> listClass = new ArrayList<String>(){
{
add("总分");
add("英语");
add("政治");
add("总分");
add("数学");
}
};

自定义条件排序方案一 Comparator

    //自定义条件排序方案一
@Test
public void test6(){ Collections.sort(listClass,new Comparator<String>() { @Override
public int compare(String o1, String o2) {
//int indexOf(String str) :返回第一次出现的指定子字符串在此字符串中的索引。
int io1 = definedOrder .indexOf(o1);
int io2 = definedOrder .indexOf(o2);
return io1-io2;
}
}); for(String s:listClass){
System.out.print(s+" ");
}
//打印结果:数学 英语 政治 总分 总分
}

自定义条件排序方案二 Lambda

    //自定义条件排序方案二 使用Lambda表达式优化比较器代码
@Test
public void test7(){
Collections.sort(listClass,(s1,s2)->definedOrder.indexOf(s1) - definedOrder.indexOf(s2));
listClass.forEach(System.out::print);
}

分组场景


使用Comparatorfor循环处理列表,来进行分类;通过调用者实现Comparator接口的比较逻辑,来告诉程序应该怎么比较,通过比较之后得结果来进行分组。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

下面例子中分别按照狗狗的颜色和体重级别两个维度来进行分组,因此分组的核心逻辑其实就是比较逻辑。相面我抽了一个工具方法:dividerList,第一个参数为需要处理的数据源,第二参数是分组时的比较逻辑。

公共代码

  @Data
@AllArgsConstructor
@ToString
class Apple {
public String color;
public int weight;
}
List<Apple> list = new ArrayList<Apple>(){
{
add(new Apple("红", 205));
add(new Apple("红", 131));
add(new Apple("绿", 248));
add(new Apple("绿", 22));
add(new Apple("黄", 119));
add(new Apple("黄", 224));
add(new Apple("白", 2024));
}
}; /**
* 是否为同一组的判断标准 参数一:需要处理的数据源 datas,参数二分组时的比较逻辑c
*/
public static <T> List<List<T>> divider(Collection<T> datas, Comparator<? super T> c) {
List<List<T>> result = new ArrayList<List<T>>();
for (T t : datas) {
boolean isSameGroup = false;
for (int j = 0; j < result.size(); j++) {
if (c.compare(t, result.get(j).get(0)) == 0) {
isSameGroup = true;
result.get(j).add(t);
break;
}
}
if (!isSameGroup) {
// 创建
List<T> innerList = new ArrayList<T>();
result.add(innerList);
innerList.add(t);
}
}
return result;
}

Comparator实现按颜色分组

    @Test
public void test1(){
List<List<Apple>> byColors = divider(list, new Comparator<Apple>() {
//按照颜色基本进行分组
@Override
public int compare(Apple o1, Apple o2) {
// 按颜色分组
return o1.color.compareTo(o2.color);
}
});
System.out.println("按颜色分组" + byColors);
}

Lambda优化按颜色分组

    /**
*使用lambda优化(按照颜色分组)
*/
@Test
public void test1_1() {
//按照颜色重量级分组
divider_Lambda(list, (o1, o2) -> o1.color.compareTo(o2.color)).forEach(System.out::println);
}

Comparator实现按分组

    @Test
public void test2(){
//按照重量级进行分组
List<List<Apple>> byWeight = divider(list, new Comparator<Apple>() { @Override
public int compare(Apple o1, Apple o2) {
// 按重量级
return (o1.getWeight() / 100 == o2.getWeight() / 100) ? 0 : 1;
}
});
byWeight.forEach(x-> System.out.println("按照总量分组:"+x));
//System.out.println("按重量级分组" + byWeight);
}

Lambda优化按重量级分组

    /**
*使用lambda优化(按照重量级进行分组)
*/
@Test
public void test2_1() {
//按照颜色分组
divider_Lambda(list, (o1, o2) -> (o1.getWeight() / 100 == o2.getWeight() / 100) ? 0 : 1).forEach(System.out::println);
}

Comparator接口常用的方法

公共代码

实体类

Persons实体类

package com.zy.pagehelper.model;

import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor; import java.math.BigDecimal; @Data
@NoArgsConstructor
@Builder
public class Persons implements Comparable {
private String name;
private BigDecimal age;
private Integer height;
private Student student; public Persons(String name, BigDecimal age, Integer height) {
this.name = name;
this.age = age;
this.height = height;
this.student = new Student(0);
} public Persons(String name, BigDecimal age, Integer height, Student student) {
this.name = name;
this.age = age;
this.height = height;
this.student = student;
} @Override
public int compareTo(Object o) {
Persons p1 = (Persons) o; if (this.age.equals(p1.age)) {
return p1.height - this.height;
}
return this.age.compareTo(p1.age);
}
}

Student实体类

package com.zy.pagehelper.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Comparator; @Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Comparator { private int age; @Override
public int compare(Object o1, Object o2) { Student p1 = (Student) o1;
Student p2 = (Student) o2; int result = Integer.compare(p1.age, p2.age); result = result == 0 ? ((p1.age > p2.age) ? 1 : -1) : result; return result;
}
}

公共集合

    Persons persons = new Persons();
List<Persons> personList = new ArrayList<Persons>() {
{
add(new Persons("a", new BigDecimal(12), 170));
add(new Persons("b", new BigDecimal(24), 175, new Student(27)));
add(new Persons("c", new BigDecimal(12), 177));
add(new Persons("a", new BigDecimal(12), 177));
add(new Persons("b", new BigDecimal(54), 174, new Student(19)));
}
};

naturalOrder 方法


naturalOrder - 自然比较,根据实体类定义的Comparable进行比较!

示例代码:

    @Test
public void testNaturalOrder(){
// naturalOrder 自然比较,根据实体类定义的Comparable
System.out.println("naturalOrder : ");
personList.sort(Comparator.naturalOrder());
personList.forEach(System.out::println);
}

comparing方法


comparing、comparingLong、comparingInt、comparingDouble - 常用比较方法,可以指定参数类型

comparing方法参数是一个函数式接口keyExtractor,意识即为指定排序对象中的排序键,这里注意排序键这里标注了Comparable接口

comparing方法

    /**
* Accepts a function that extracts a {@link java.lang.Comparable
* Comparable} sort key from a type {@code T}, and returns a {@code
* Comparator<T>} that compares by that sort key.
*
* <p>The returned comparator is serializable if the specified function
* is also serializable.
*
* @apiNote
* For example, to obtain a {@code Comparator} that compares {@code
* Person} objects by their last name,
*
* <pre>{@code
* Comparator<Person> byLastName = Comparator.comparing(Person::getLastName);
* }</pre>
*/
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));
}

comparing方法参数是一个函数式接口keyExtractor,意识即为指定排序对象中的排序键,这里注意排序键这里标注了Comparable接口。

同时我们也可以看到有重载的comparing方法:

   /**
* Accepts a function that extracts a sort key from a type {@code T}, and
* returns a {@code Comparator<T>} that compares by that sort key using
* the specified {@link Comparator}.
*
* <p>The returned comparator is serializable if the specified function
* and comparator are both serializable.
*
* @apiNote
* For example, to obtain a {@code Comparator} that compares {@code
* Person} objects by their last name ignoring case differences,
*
* <pre>{@code
* Comparator<Person> cmp = Comparator.comparing(
* Person::getLastName,
* String.CASE_INSENSITIVE_ORDER);
* }</pre>
*/
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));
}

第二个参数也很好理解,提取完sort key之后,要定义关于这个key的Comparator,在注释中的例子也比较好理解。 这里有个小tips:在String类中,提供了一个实现Comparator接口的常量来标识不对语言敏感的字典序排序器。

 /**
* A Comparator that orders {@code String} objects as by
* {@code compareToIgnoreCase}. This comparator is serializable.
* <p>
* Note that this Comparator does <em>not</em> take locale into account,
* and will result in an unsatisfactory ordering for certain locales.
* The java.text package provides <em>Collators</em> to allow
* locale-sensitive ordering.
*
* @see java.text.Collator#compare(String, String)
* @since 1.2
*/
public static final Comparator<String> CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator();
private static class CaseInsensitiveComparator
implements Comparator<String>, java.io.Serializable {
// use serialVersionUID from JDK 1.2.2 for interoperability
private static final long serialVersionUID = 8575799808933029326L; public int compare(String s1, String s2) {
int n1 = s1.length();
int n2 = s2.length();
int min = Math.min(n1, n2);
for (int i = 0; i < min; i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
if (c1 != c2) {
c1 = Character.toUpperCase(c1);
c2 = Character.toUpperCase(c2);
if (c1 != c2) {
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
if (c1 != c2) {
// No overflow because of numeric promotion
return c1 - c2;
}
}
}
}
return n1 - n2;
} /** Replaces the de-serialized object. */
private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
} // 这里其实可以看到compareToIgnoreCase也是调用了这个实例的compare方法
public int compareToIgnoreCase(String str) {
return CASE_INSENSITIVE_ORDER.compare(this, str);
}

在Comparator接口中,也直接提供了具体类型的三个comparing方法:

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));
}

测试示例代码:

    @Test
public void testComparing(){
//comparing、comparingLong、comparingInt、comparingDouble - 常用比较方法,可以指定参数类型 // comparing 1.0 比较集合中对象的年龄,取最大值
Optional<Persons> optional = personList.stream().max(Comparator.comparing(Persons::getAge));
System.out.println("comparing 1.0 : get max age " + optional.get().toString() + "\n"); // comparing 2.1
optional = personList.stream().max(Comparator.comparing(Persons::getName, Comparator.reverseOrder()));
System.out.println("comparing 2.1 : get min name " + optional.get().toString() + "\n"); // comparing 2.2
optional = personList.stream().max(Comparator.comparing(Persons::getName, String::compareTo));
System.out.println("comparing 2.2 : get max name " + optional.get().toString() + "\n"); // comparing 2.3 该方法多了一个参数 keyComparator ,keyComparator 是创建一个自定义的比较器。示例种:通过cmmpare()方法进行学生年龄比较,
optional = personList.stream().max(Comparator.comparing(Persons::getStudent, (o1, o2) -> new Student().compare(o1, o2)));
System.out.println("comparing 2.3 : get max student.age " + optional.get().toString() + "\n"); }
/*
打印结果
comparing 1.0 : get max age Persons(name=b, age=54, height=174, student=Student(age=19)) comparing 2.1 : get min name Persons(name=a, age=12, height=170, student=Student(age=0)) comparing 2.2 : get max name Persons(name=c, age=12, height=177, student=Student(age=0)) comparing 2.3 : get max student.age Persons(name=b, age=24, height=175, student=Student(age=27))
*/ // 升序 comparing方法的具体实现一comparingInt
System.out.println("升序 : ");
personList.sort(Comparator.comparingInt(Persons::getHeight));
personList.forEach(System.out::println); // 降序 comparing方法的具体实现二comparingInt
System.out.println("降序 : ");
personList.sort(Comparator.comparingInt(Persons::getHeight).reversed());
personList.forEach(System.out::println);

thenComparing方法


/**
* Returns a lexicographic-order comparator with another comparator.
* If this {@code Comparator} considers two elements equal, i.e.
* {@code compare(a, b) == 0}, {@code other} is used to determine the order.
*
* <p>The returned comparator is serializable if the specified comparator
* is also serializable.
*
* @apiNote
* For example, to sort a collection of {@code String} based on the length
* and then case-insensitive natural ordering, the comparator can be
* composed using following code,
*
* <pre>{@code
* Comparator<String> cmp = Comparator.comparingInt(String::length)
* .thenComparing(String.CASE_INSENSITIVE_ORDER);
* }</pre>
*/
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);
};
}

从方法名称上知道这是当比较相同时的使用的一个排序规则,这里需要注意看具体实现是会先调用比较器实例中的compare方法来进行比较一轮,当结果等于0的时候才会调用other这个比较器规则进行比较。比如下面的一个DOME:

List<String> strings = Arrays.asList("def", "abc", "hel", "world");
strings.sort(Comparator.comparingInt(String::length).reversed() //(1)
.thenComparing(String::compareToIgnoreCase) // (2)
.thenComparing(Comparator.reverseOrder()) // (3)这个比较器不会被应用 因为比较器(2)已经把结果比较出来了,并且没有相等的结果,这里不会再应用(3)比较器
); System.out.println(strings); // 输出[world, abc, def, hel]

当然因为有了 comparing方法的支持,所以也就有了下面两个thenComparing的重载方法

  default <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
{
return thenComparing(comparing(keyExtractor));
}
 default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
return thenComparing(comparing(keyExtractor, keyComparator));
}

测试示例代码:

    @Test
public void test2(){
//根据第一个属性进行排序,如果相同则以此根据下一个thenComparing()中的属性进行排序 // thenComparing 1.0
System.out.println("thenComparing 1.0 : ");
personList.sort(Comparator.comparing(Persons::getAge));
personList.forEach(System.out::println); // thenComparing 1.1
System.out.println("thenComparing 1.1 : ");
personList.sort(Comparator.comparing(Persons::getAge).thenComparing(Persons::getHeight));
personList.forEach(System.out::println); // thenComparing 2.0
System.out.println("thenComparing 2.0 : ");
personList.sort(Comparator.comparing(Persons::getAge).thenComparing(Persons::getHeight).thenComparing(Persons::getName));
personList.forEach(System.out::println); }

nullsLast()/nullsFirst()


Comparator接口中有两个对null友好的比较器方法:

   /**
* Returns a null-friendly comparator that considers {@code null} to be
* less than non-null. When both are {@code null}, they are considered
* equal. If both are non-null, the specified {@code Comparator} is used
* to determine the order. If the specified comparator is {@code null},
* then the returned comparator considers all non-null values to be equal.
*
* <p>The returned comparator is serializable if the specified comparator
* is serializable.
*
* @param <T> the type of the elements to be compared
* @param comparator a {@code Comparator} for comparing non-null values
* @return a comparator that considers {@code null} to be less than
* non-null, and compares non-null objects with the supplied
* {@code Comparator}.
* @since 1.8
*/
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(true, comparator);
} // null比非null元素都大的
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(false, comparator);
}

这里是通过Comparators这个工厂类提供的NullComparator比较器实现的,看到注释有一条需要注意是如果不指定comparator参数,即传入null,那么所有的非null参数都会被视为相等。

当集合中存在null元素时,可以使用针对null友好的比较器,null元素排在集合的最前面/最后面

测试示例代码

    @Test
public void testNulls() { // nullsLast
System.out.println("nullsLast : ");
personList.sort(Comparator.nullsLast(Comparator.comparing(Persons::getName)));
personList.forEach(System.out::println); // nullsFirst
System.out.println("nullsFirst : ");
personList.sort(Comparator.nullsFirst(Comparator.comparing(Persons::getName)));
personList.forEach(System.out::println);
}

Comparator接口和Comparable接口

这两个接口首先要做一个简单区别。

Comparable接口

* Lists (and arrays) of objects that implement this interface can be sorted
* automatically by {@link Collections#sort(List) Collections.sort} (and
* {@link Arrays#sort(Object[]) Arrays.sort}). Objects that implement this
* interface can be used as keys in a {@linkplain SortedMap sorted map} or as
* elements in a {@linkplain SortedSet sorted set}, without the need to
* specify a {@linkplain Comparator comparator}.<p>

可以看到注释中说明了实现了该接口的对象,在数组中可以使用Collections.sort或者Arrays.sort方法实现排序,或者实现了该接口的对象可以作为sortedMap或者SortedSet的key。这里也提到我们不用制定一个排序或者作为key的Comparator接口。

public interface Comparable<T> {
/**
* 省略部分注释
* <p>The implementor must ensure <tt>sgn(x.compareTo(y)) ==
* -sgn(y.compareTo(x))</tt> for all <tt>x</tt> and <tt>y</tt>. (This
* implies that <tt>x.compareTo(y)</tt> must throw an exception iff
* <tt>y.compareTo(x)</tt> throws an exception.)
*/
public int compareTo(T o);
}

compareTo方法上的注释中提到,必须确保 x.compareTo(y)y.compareTo(x)的结果是一致的,并且这也意味着当x.compartTo(y)抛出一个异常,那么y.compareTo(x)也应该去抛出一个异常,那么这里就思考到了一个关于null的设计:null.compareTo(obj)我们肯定知道会有NPE,那么你在实现compareTo方法的时候,如果obj.compareTo(null)这里也应该去抛出NPE。

这里就不去写具体的demo去演示了,这里理解为一个对象实现了Comparable接口,那么这个对象就是可比较的,并且在排序等场景下调用实现接口中的compareTo方法。

Comparator接口

Comparator接口要理解为比较器,实现其接口的类其实是比较器的一种实现,相当于一个比较的函数定义。来看下他的注释:

* A comparison function, which imposes a <i>total ordering</i> on some
* collection of objects. Comparators can be passed to a sort method (such
* as {@link Collections#sort(List,Comparator) Collections.sort} or {@link
* Arrays#sort(Object[],Comparator) Arrays.sort}) to allow precise control
* over the sort order. Comparators can also be used to control the order of
* certain data structures (such as {@link SortedSet sorted sets} or {@link
* SortedMap sorted maps}), or to provide an ordering for collections of
* objects that don't have a {@link Comparable natural ordering}.<p>

这里我们看到Arrays、Collections也提供了重载的sort方法,支持传入一个集合/数组和Comparator接口的实例。当然当前列表/数组中的对象不一定是实现了Comparable接口。

类实现了comparable接口之后,可以直接调用排序方法;而当使用comparator时,不需要类实现,具体使用时(也就是调用某些方法时)的需要类和该comparator绑定起来来实现。comparable实现内部排序,Comparator是外部排序。

Comparator比较器的更多相关文章

  1. java.util下有一个Comparator(比较器)

    java.util下有一个Comparator(比较器) 它拥有compare(),用来比较两个方法. 要生成比较器,则用Sort中Sort(List,List(Compate)) 第二种方法更灵活, ...

  2. Comparable比较器和Comparator比较器

    1.Comparable比较器 在Arrays类中存在sort()排序方法,此方法可以直接对对象数组进行排序. public static void sort(Object[] a 根据元素的自然顺序 ...

  3. 2.3 comparator(比较器)

    1.comparator是java的一种机制,用来帮助我们给相同对象的不同属性排序 2.Comparable接口,是一个对象本身就已经支持自比较所需要实现的接口,如String,Integer自己就已 ...

  4. java中Comparator比较器顺序问题,源码分析

    提示: 分析过程是个人的一些理解,如有不对的地方,还请大家见谅,指出错误,共同学习. 源码分析过程中由于我写的注释比较啰嗦.比较多,导致文中源代码不清晰,还请一遍参照源代码,一遍参照本文进行阅读. 原 ...

  5. 菜鸡的Java笔记 comparator 比较器

    1.数组操作类: Arrays        2.两种比较器的使用: Comparable Comparator        3.实现二叉树算法            content (内容)   ...

  6. java:Comparator比较器

    /*Comparator是java.util包里的一个接口,使用时应该实现导入相应的包, *再写一个实现了Comparator接口的类,并复写int compare(Object o)方法, *写出你 ...

  7. Java Object类 instanceof关键字 练习:判断是否为同一人 集合按照人的年龄排序,如果年龄相同按名字的字母顺序升序 Comparator比较器

    package com.swift; public class Same_Person_Test { public static void main(String[] args) { /* * Obj ...

  8. java Comparator比较器排序法

    注意:排序的字段不为空,否则抛出空指针异常! 第一步:先编写一个比较器类 如下: 第二步:此集合的对象 EO 必须重写 此equals 方法 如图: 第三步:调用使用此比较器 如图:

  9. Java之ArrayList自定义排序,通过实现comparator比较器接口

    两种排序方式: 1.实体类实现Comparable接口,重写compareTo(T o)方法,在其中定义排序规则,那么就可以直接调用Collections.sort()来排序对象数组 2.在调用方法的 ...

随机推荐

  1. 观察者模式EventBus

    EventBus能够简化各组件间的通信,让我们的代码书写变得简单,能有效的分离事件发送方和接收方(也就是解耦的意思),能避免复杂和容易出错的依赖性和生命周期问题. implementation 'or ...

  2. SQL Server 列存储索引概述

    第一次接触ColumnStore是在2017年,数据库环境是SQL Server 2012,Microsoft开始在SQL Server 2012中推广列存储索引,到现在的SQL Server 201 ...

  3. PAT Saving James Bond - Easy Version

    Saving James Bond - Easy Version This time let us consider the situation in the movie "Live and ...

  4. 【应用程序见解 Application Insights】Application Insights 使用 Application Maps 构建请求链路视图

    Applicaotn  Insigths 使用 Application Maps 构建请求链路视图 构建系统时,请求的逻辑操作大多数情况下都需要在不同的服务,或接口中完成整个请求链路.一个请求可以经历 ...

  5. 「SHOI2014」三叉神经树

    「SHOI2014」三叉神经树 给你一颗由\(n\)个非叶子结点和\(2n+1\)个叶子结点构成的完全三叉树,每个叶子结点有一个输出:\(0\)或\(1\),每个非叶子结点的输出为自己的叶子结点中较多 ...

  6. delphi key解密转c# 解决string 不可变长度问题

    遇见问题: delphi的解密需要在c#里面实现 方法一:delphi编写delphi dll组件,c#里面调用 方法二:c#重写delphi的代码进行解析 方法一: delphi部分代码: libr ...

  7. leetcode116:search-for-a-range

    题目描述 给出一个有序数组,请在数组中找出目标值的起始位置和结束位置 你的算法的时间复杂度应该在O(log n)之内 如果数组中不存在目标,返回[-1, -1]. 例如: 给出的数组是[5, 7, 7 ...

  8. tp3.2 前端截取字符串

    在Common目录中建立 function.php <?php function subtext($text, $length) { if(mb_strlen($text, 'utf8') &g ...

  9. 写博客真的很枯燥,更麻烦的是我还不会MD,排版太不友好了啊。

    学习MD 第一标题 #一号标题 ##二号标题 神马啊,博客园居然不支持MD语法

  10. JS多物体宽度运动案例

    任务 对于每一个Div区块,鼠标移入,宽度逐渐变宽,最宽值为400px,当鼠标移除时,宽度逐渐减小,最小值为100px. 任务提示: (1)多物体运动的定时器需要需要每个物体上同时最多只能开一个定时器 ...