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;
}
@Override
public 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;
}
@Override
public 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;
}
@Override
public int compareTo(Person other) {
int ageComparison = this.age - other.age;
if (ageComparison != 0) {
return ageComparison;
}
return this.name.compareTo(other.name);
}
@Override
public 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>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println(Arrays.toString(arr1));
Arrays.sort(arr1, new Comparator<Integer>() {
@Override
public 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;
}
@Override
public 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>() {
@Override
public int compare(StuComparator o1, StuComparator o2) {
return o1.age - o2.age;
}
});
System.out.println(Arrays.toString(stu));
Arrays.sort(stu, new Comparator<StuComparator>() {
@Override
public int compare(StuComparator o1, StuComparator o2) {
return Double.compare(o1.height, o2.height);
}
});
System.out.println(Arrays.toString(stu));
}
}