String类的Comparable接口
1、String类实现了Comparable<String>接口,并提供了compareTo方法的实现,因此,字符串对象(即String类型的实例)可以直接调用compareTo()方法来比较它们。2、String类的compareTo()方法是这样工作的:它按照字典顺序比较两个字符串,从两个字符串的第一个字符开始比较,如果它们相等,则继续比较下一个字符,直到找到不同的字符或者到达字符串的末尾,如果所有的字符都相同,那么较短的字符串被认为是较小的。
排序
Comparable接口
"实现Comparable接口 ,就必须重写它的compareTo()方法""Comparable接口"是一个泛型接口,在类的声明中使用泛型参数,来指定需要比较的对象类型,它包含一个compareTo()方法,如下所示:public interface Comparable<T> {int compareTo(T o);}"compareTo()方法",返回一个整数值,用于表示当前对象,与另一个对象的比较结果。通常,它有以下三种返回值:如果,当前对象 小于 另一个对象,则返回,负整数。如果,当前对象 等于 另一个对象,则返回,零。如果,当前对象 大于 另一个对象,则返回,正整数。使用的场景:1、具体的类A,实现Comparable接口2、重写Comparable接口中的compareTo(Object obj)方法,在此方法中指明比较类A的对象的大小的标准3、创建类A的多个实例,进行大小的比较或排序。
实现Comparable接口
要使一个类可以进行自然排序,需要实现"Comparable接口"并提供"compareTo()方法的具体实现",在compareTo()方法中,你需要指定对象之间的比较规则,如:
"Student.java"
public class Student implements Comparable<Student> {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic int compareTo (Student other){return this.age - other.age;}public String toString() {return "Student{name='" + name + "', age=" + age + '}';}
}
Student类实现了Comparable<Student>接口,并重写了compareTo()方法,按照年龄升序排序,是通过比较当前对象的年龄属性和另一个对象的年龄属性来实现的。"MyTest.java"
import java.util.TreeSet;
public class MyTest {public static void main(String[] args) {TreeSet<Student> studentSet = new TreeSet<>();studentSet.add(new Student("Alice", 22));studentSet.add(new Student("Bob", 20));studentSet.add(new Student("Charlie", 25));for (Student student : studentSet) {System.out.println(student);}}
}
"对上面的代码做一下解释"在Java中,当你创建一个实现了Comparable接口的类的实例,并将其放入一个TreeSet集合时,TreeSet会自动使用该类实现的compareTo()方法来对集合中的元素进行排序,你不需要显式地调用compareTo()方法,因为,TreeSet内部在需要时会自动调用它。另:1、创建TreeSet实例:当你创建 "TreeSet<Student> studentSet" 时,实际上是在告诉Java你想要一个有序的、不重复的集合,该集合将包含Student类型的对象。2、添加元素到TreeSet:当你调用 "studentSet.add(new Student("Alice", 22))" 等方法添加元素时,TreeSet内部会检查新元素与集合中已存在元素的顺序关系,这是通过调用新元素的compareTo方法实现的。3、自动排序:在TreeSet内部,元素是以红黑树的结构存储的,当你添加一个新元素时,TreeSet会使用compareTo()方法来确定新元素在树中的正确位置,以保持集合的有序性,这个过程是自动的,你不需要显式地调用任何排序方法。4、遍历TreeSet:当你遍历TreeSet时(使用for-each循环),你会看到元素已经按照compareTo方法定义的顺序排列好了。这个例子中,Student类实现了Comparable<Student>接口,并重写了compareTo方法,该方法比较两个Student对象的age属性,因此,当你将Student对象添加到TreeSet时,它们会按照年龄升序排列。
Collections.sort
"Student.java"
public class Student implements Comparable<Student>{private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic int compareTo(Student other) {return this.age - other.age;}public String toString() {return "Student{name='" + name + "', age=" + age + '}';}
}import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Test1 {public static void main(String[] args) {List<Student> list = new ArrayList<>();list.add(new Student("Alice", 22));list.add(new Student("White", 18));list.add(new Student("Black", 30));Collections.sort(list);for (Student stu : list){System.out.println(stu);}}
}为什么 Collections.sort(list) 会使用 Student类的compareTo()方法进行排序呢?因为,Student类实现了Comparable<Student>接口并重写了compareTo()方法,所以,当你调用 Collections.sort(list)时,该方法会自动调用,Student类中的compareTo()方法,来比较对象并进行排序。
自定义排序
"要求"有时,需要对对象进行多属性排序,例如,先按年龄升序排序,然后按姓名字母顺序排序,为了实现多属性排序,可以在 compareTo()方法中逐一比较不同属性,确保按照所需顺序比较。"Person.java"
public class Person implements Comparable<Person>{String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic int compareTo(Person other) {int ageComparison = this.age - other.age;if (ageComparison != 0) {return ageComparison;}return this.name.compareTo(other.name);}@Overridepublic String toString() {return "Student{name='" + name + "', age=" + age + '}';}
}import java.util.Collections;
import java.util.List;
public class PersonTest {public static void main(String[] args) {List<Person> list = new ArrayList<>();list.add(new Person("Wang", 26));list.add(new Person("King", 19));list.add(new Person("He", 19));list.add(new Person("Black", 28));Collections.sort(list);for (Person per : list) {System.out.println(per);}}
}
Comparator定制排序
什么时候使用?当,元素的类型没有实现java.lang.Comparable接口,而又不方便修改代码(比如JDK当中的类),或者,实现了java.lang.Comparable接口,但定义好的排序规则不适合当前的操作,那么,可以考虑使用接口Comparator的对象来排序,强行对多个对象进行整体排序的比较。1、public interface Comparator<T>Comparator属于接口且支持范型,位于java.util包下2、Comparator接口,内置实现自定义排序的抽象方法compare(),int compare(T o1,T o2),T:泛型,这个方法是让两个形参对象去比较大小。重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果,返回,正整数,则表示o1大于o2如果,返回0,表示相等如果,返回负整数,表示 o1小于o2需要在compare中指明o1和o2按照什么规则比较3、可以将Comparator传递给sort方法(如 Collections.sort或Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用 Comparator 来控制某些数据结构(如有序set 或 有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。
Arrays类下的sort方法
public static <T> void sort(T[] a, Comparator<? super T> c)
对基本数据类型的排序
import java.util.Arrays;
import java.util.Comparator;public class TestComparator {public static void main(String[] args) {Integer[] arr1 = {1,4,2,3};Arrays.sort(arr1, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1;}});System.out.println(Arrays.toString(arr1)); Arrays.sort(arr1, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o1 - o2;}});System.out.println(Arrays.toString(arr1)); }
}
对象数组的排序
"StuComparator.java"
public class StuComparator {String name;int age;double height;public StuComparator() {}public StuComparator(String name, int age, double height) {this.name = name;this.age = age;this.height = height;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public double getHeight() {return height;}public void setHeight(double height) {this.height = height;}@Overridepublic String toString() {return "\n" + "name=" + name + ", age=" + age + ", height=" + height + " \n";}
}"TestStuComparator.java"
import java.util.Arrays;
import java.util.Comparator;
public class TestStuComparator {public static void main(String[] args) {StuComparator[] stu = new StuComparator[4];stu[0] = new StuComparator("张三", 16, 176.6);stu[1] = new StuComparator("李四", 25, 181.3);stu[2] = new StuComparator("小明", 18, 179.4);stu[3] = new StuComparator("小红", 17, 165);Arrays.sort(stu, new Comparator<StuComparator>() {@Overridepublic int compare(StuComparator o1, StuComparator o2) {return o1.age - o2.age;}});System.out.println(Arrays.toString(stu));Arrays.sort(stu, new Comparator<StuComparator>() {@Overridepublic int compare(StuComparator o1, StuComparator o2) {return Double.compare(o1.height, o2.height);}});System.out.println(Arrays.toString(stu));}
}