菜单
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS R TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI GO KOTLIN SASS VUE DSA GEN AI SCIPY AWS CYBERSECURITY DATA SCIENCE
     ❯   

Java 教程

Java HOME Java Intro Java Get Started Java Syntax Java Output Java Comments Java Variables Java Data Types Java Type Casting Java Operators Java Strings Java Math Java Booleans Java If...Else Java Switch Java While Loop Java For Loop Java Break/Continue Java Arrays

Java Methods

Java Methods Java Method Parameters Java Method Overloading Java Scope Java Recursion

Java Classes

Java OOP Java 类/对象 Java 类属性 Java 类方法 Java 构造函数 Java 修饰符 Java 封装 Java 包/API Java 继承 Java 多态 Java 内部类 Java 抽象 Java 接口 Java 枚举 Java 用户输入 Java 日期 Java ArrayList Java LinkedList Java 列表排序 Java HashMap Java HashSet Java Iterator Java 包装类 Java 异常 Java 正则表达式 Java 线程 Java Lambda Java 高级排序

Java File Handling

Java Files Java Create/Write Files Java Read Files Java Delete Files

Java How To's

相加两个数 计算单词数 反转字符串 数组元素求和 字符串转数组 排序数组 计算数组平均值 查找数组最小元素 ArrayList 循环 HashMap 循环 枚举循环 矩形面积 偶数或奇数 正数或负数 平方根 随机数

Java 参考

Java Reference Java Keywords Java String Methods Java Math Methods Java Output Methods Java Arrays Methods Java ArrayList Methods Java LinkedList Methods Java HashMap Methods Java Scanner Methods Java Iterator Methods Java Errors & Exceptions

Java 示例

Java Examples Java Compiler Java Exercises Java Quiz Java Server Java Certificate


Java 高级排序(Comparator 和 Comparable)


Java 高级排序

列表排序章节 中,您学习了如何按字母顺序和数字顺序对列表进行排序,但如果列表中包含对象呢?

要对对象进行排序,您需要指定一个决定对象如何排序的规则。例如,如果您有一系列汽车,您可能希望按年份对它们进行排序,规则可以是较早年份的汽车在前。

ComparatorComparable 接口允许您指定用于对对象进行排序的规则。

能够指定排序规则也允许您更改字符串和数字的排序方式。


Comparators(比较器)

实现 Comparator 接口的对象称为比较器。

Comparator 接口允许您创建一个具有 compare() 方法的类,该方法比较两个对象以决定哪个对象在列表中应该排在前面。

compare() 方法应返回一个数字,该数字是

  • 负数,如果第一个对象应该排在列表前面。
  • 正数,如果第二个对象应该排在列表前面。
  • 零,如果顺序无关紧要。

实现 Comparator 接口的类可能看起来像这样

// Sort Car objects by year
class SortByYear implements Comparator {
  public int compare(Object obj1, Object obj2) {
    // Make sure that the objects are Car objects
    Car a = (Car) obj1;
    Car b = (Car) obj2;
    
    // Compare the objects
    if (a.year < b.year) return -1; // The first car has a smaller year
    if (a.year > b.year) return 1;  // The first car has a larger year
    return 0; // Both cars have the same year
  }
}

要使用比较器,请将其作为参数传递给排序方法

// Use a comparator to sort the cars
Comparator myComparator = new SortByYear();
Collections.sort(myCars, myComparator);

以下是使用比较器按年份对汽车列表进行排序的完整示例

示例

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

// Define a Car class
class Car {
  public String brand;
  public String model;
  public int year;
  
  public Car(String b, String m, int y) {
    brand = b;
    model = m;
    year = y;
  }
}

// Create a comparator
class SortByYear implements Comparator {
  public int compare(Object obj1, Object obj2) {
    // Make sure that the objects are Car objects
    Car a = (Car) obj1;
    Car b = (Car) obj2;
    
    // Compare the year of both objects
    if (a.year < b.year) return -1; // The first car has a smaller year
    if (a.year > b.year) return 1;  // The first car has a larger year
    return 0; // Both cars have the same year
  }
}

public class Main { 
  public static void main(String[] args) { 
    // Create a list of cars
    ArrayList<Car> myCars = new ArrayList<Car>();    
    myCars.add(new Car("BMW", "X5", 1999));
    myCars.add(new Car("Honda", "Accord", 2006));
    myCars.add(new Car("Ford", "Mustang", 1970));

    // Use a comparator to sort the cars
    Comparator myComparator = new SortByYear();
    Collections.sort(myCars, myComparator);

    // Display the cars
    for (Car c : myCars) {
      System.out.println(c.brand + " " + c.model + " " + c.year);
    }
  } 
}
自己动手试一试 »

使用 Lambda 表达式

为了使代码更短,比较器可以用 lambda 表达式替换,该表达式具有与 compare() 方法相同的参数和返回值

示例

使用 lambda 表达式作为比较器

Collections.sort(myCars, (obj1, obj2) -> {
  Car a = (Car) obj1;
  Car b = (Car) obj2;
  if (a.year < b.year) return -1;
  if (a.year > b.year) return 1;
  return 0;
});
自己动手试一试 »

特殊排序规则

比较器还可以用于为字符串和数字创建特殊的排序规则。在此示例中,我们使用比较器将所有偶数排在奇数之前

示例

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

class SortEvenFirst implements Comparator {
  public int compare(Object obj1, Object obj2) {
    // Make sure the objects are integers
    Integer a = (Integer)obj1;
    Integer b = (Integer)obj2;
    
    // Check each number to see if it is even
    // A number is even if the remainder when dividing by 2 is 0
    boolean aIsEven = (a % 2) == 0;
    boolean bIsEven = (b % 2) == 0;
    
    if (aIsEven == bIsEven) {
    
      // If both numbers are even or both are odd then use normal sorting rules
      if (a < b) return -1;
      if (a > b) return 1;
      return 0;
      
    } else {
    
      // If a is even then it goes first, otherwise b goes first
      if (aIsEven) {
      	return -1;
      } else {
        return 1;
      }
    }
  }
}

public class Main {
  public static void main(String[] args) {
    ArrayList<Integer> myNumbers = new ArrayList<Integer>();
    myNumbers.add(33);
    myNumbers.add(15);
    myNumbers.add(20);
    myNumbers.add(34);
    myNumbers.add(8);
    myNumbers.add(12);

    Comparator myComparator = new SortEvenFirst();
    Collections.sort(myNumbers, myComparator);

    for (int i : myNumbers) {
      System.out.println(i);
    }
  }
}
自己动手试一试 »

Comparable 接口

Comparable 接口允许对象通过 compareTo() 方法指定其自身的排序规则。

compareTo() 方法接受一个对象作为参数,并将可比较对象与该参数进行比较,以决定哪个对象在列表中应该排在前面。

与比较器一样,compareTo() 方法返回一个数字,该数字是

  • 负数,如果可比较对象应该排在列表前面。
  • 正数,如果另一个对象应该排在列表前面。
  • 零,如果顺序无关紧要。

许多原生的 Java 类都实现了 Comparable 接口,例如 StringInteger

这就是为什么字符串和数字不需要比较器就可以排序的原因。

实现 Comparable 接口的对象可能看起来像这样

class Car implements Comparable {
  public String brand;
  public String model;
  public int year;
  
  // Decide how this object compares to other objects
  public int compareTo(Object obj) {
  	Car other = (Car)obj;
    if(year < other.year) return -1; // This object is smaller than the other one
    if(year > other.year) return 1;  // This object is larger than the other one
    return 0; // Both objects are the same
  }
}

这是与之前相同的示例,但使用了 Comparable 接口而不是比较器

示例

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

// Define a Car class which is comparable
class Car implements Comparable {
  public String brand;
  public String model;
  public int year;
  
  public Car(String b, String m, int y) {
    brand = b;
    model = m;
    year = y;
  }
  
  // Decide how this object compares to other objects
  public int compareTo(Object obj) {
  	Car other = (Car)obj;
    if(year < other.year) return -1; // This object is smaller than the other one
    if(year > other.year) return 1;  // This object is larger than the other one
    return 0; // Both objects are the same
  }
}

public class Main { 
  public static void main(String[] args) { 
    // Create a list of cars
    ArrayList<Car> myCars = new ArrayList<Car>();    
    myCars.add(new Car("BMW", "X5", 1999));
    myCars.add(new Car("Honda", "Accord", 2006));
    myCars.add(new Car("Ford", "Mustang", 1970));

    // Sort the cars
    Collections.sort(myCars);

    // Display the cars
    for (Car c : myCars) {
      System.out.println(c.brand + " " + c.model + " " + c.year);
    }
  } 
}
自己动手试一试 »

一个常见的排序技巧

最自然地对两个数字进行排序的方法是像这样写

if(a.year < b.year) return -1; // a is less than b
if(a.year > b.year) return 1; // a is greater than b
return 0; // a is equal to b

但实际上可以用一行代码完成

return a.year - b.year;

这个技巧也可以用来轻松地反向排序

return b.year - a.year;

Comparator 与 Comparable 的区别

比较器是一个只有一个方法且用于比较两个不同对象 Object。

可比较对象是其本身可以与其它对象进行比较的对象。

如果可能,使用 Comparable 接口会更容易,但 Comparator 接口功能更强大,因为它允许您对任何类型的对象进行排序,即使您无法更改其代码。




×

联系销售

如果您想将 W3Schools 服务用于教育机构、团队或企业,请发送电子邮件给我们
sales@w3schools.com

报告错误

如果您想报告错误,或想提出建议,请发送电子邮件给我们
help@w3schools.com

W3Schools 经过优化,旨在方便学习和培训。示例可能经过简化,以提高阅读和学习体验。教程、参考资料和示例会不断审查,以避免错误,但我们无法保证所有内容的完全正确性。使用 W3Schools 即表示您已阅读并接受我们的使用条款Cookie 和隐私政策

版权所有 1999-2024 Refsnes Data。保留所有权利。W3Schools 由 W3.CSS 提供支持