发布时间:2025-12-10 23:24:09 浏览次数:2
先上代码:
packagejava.lang;publicinterfaceComparable<T>{publicintcompareTo(To);}可以看出这个接口只有一个方法,这个方法只有一个参数,实现了这个接口的类就可以和同类进行比较了。这个方法所实现的,就是比较法则,也是说,它表示如何对两个对象进行比较。 它返回的是一个整数int:
返回正数,代表当前对象大于被比较的对象;
返回0,代表当前对象等于于被比较的对象;
返回负数,代表当前对象小于被比较的对象。
实现了该接口后,我们就可以使用Arrays.sort()和Collections.sort()来进行排序了。 不然对象没有比较法则,程序肯定是不知道如何进行比较排序的。 像我们常用的类String、Integer、Double、Date等,JDK都帮我们实现了Comparable接口,我们可以直接对这类对象进行比较排序。 举个例子,Date Comparable的实现:
publicintcompareTo(DateanotherDate){longthisTime=getMillisOf(this);longanotherTime=getMillisOf(anotherDate);return(thisTime<anotherTime?-1:(thisTime==anotherTime?0:1));}需要注意的是,当我们自己去实现Comparable接口时,一定要注意与**equals()**方法保持一致。当两个对象是equals的,compare的结果应该是相等的。
还是先看代码,看看接口定义吧:
packagejava.util;@FunctionalInterfacepublicinterfaceComparator<T>{intcompare(To1,To2);}它是一个函数式接口,它的compare方法有两个参数,代表进行比较的两个对象。这个接口代表了可以作为某种对象比较的一种法则,或叫一种策略。 它的返回值正负代表意义与Comparable接口的方法一样。 它的使用通常会有三种方式:
实现类
匿名类
Lambda表达式
在Java8之后,我们一般用Lambda比较多,也比较灵活优雅。
两个接口功能都是用于比较排序,但其实有很大的区别。
两者方法参数不同,Comparable只有一个参数,表示被比较的对象,因为它的方法是位于需要比较的类里的,所以只要一个参数就可以了;而Comparator的比较方法则有两个参数,分别表示比较对象和被比较对象。
Comparable与对象绑定,位于对象内,我们可以称之为内比较器;而Comparator是独立于需要比较的类的,我们可以称为外比较器。
当类实现了Comparable方法后,比较法则就确定了,我们称之为自然比较方法,我们无法给它实现多种比较方法;而因为Comparator独立于外,我们可以为同一个类提供多种Comparator的实现,这样来提供多种比较方法/策略,如升序倒序,因此我们也可以将Comparator看成是一种策略模式。
相对于Comparable,Comparator有一定的灵活性,假如一个类并没有实现Comparable接口,并且这个类是无法修改的,我们就要通过提供Comparator来进行比较排序。 Comparator这种模式实现了数据与算法的解耦合,对于维护也是很方便的。
十分友好的是,JDK为我们提供了工具类,它们的静态方法可以帮助我们直接对数组和List进行排序。
Arrays的sort方法可以对已经实现了Comparable接口的进行排序,同时还可指定排序的范围。
//Arrays.sort对String进行排序String[]strings={"de","dc","aA","As","k","b"};Arrays.sort(strings);assertTrue(Arrays.equals(strings,newString[]{"As","aA","b","dc","de","k"}));指定范围排序,需要注意的是,index是从0开始算的,包含fromIndex,不包含toIndex:
//Arrays.sort指定范围排序strings=newString[]{"z","a","d","b"};Arrays.sort(strings,0,3);assertTrue(Arrays.equals(strings,newString[]{"a","d","z","b"}));对于基本类型,一样可以进行排序,并不需要使用封装类:
//Arrays.sort对基本类型排序int[]nums={3,1,20,2,38,2,94};Arrays.sort(nums);assertTrue(Arrays.equals(nums,newint[]{1,2,2,3,20,38,94}));还能多线程进行排序,其实是拆分成多个子数组再进行排序,最终再合并结果。
//Arrays.parallelSort多线程排序nums=newint[]{3,1,20,2,38,2,94};Arrays.parallelSort(nums);assertTrue(Arrays.equals(nums,newint[]{1,2,2,3,20,38,94}));对于没有实现Comparable的类也可以使用,但需要提供Comparator来指定比较策略。 本文的没有实现Comparable接口的类Person如下:
importlombok.AllArgsConstructor;importlombok.Data;@Data@AllArgsConstructorpublicclassPerson{privateStringname;privateintage;}排序:
//Arrays.sort提供Comparator进行排序Person[]persons=newPerson[]{newPerson("Larry",18),newPerson("David",30),newPerson("James",20),newPerson("Harry",18)};Arrays.sort(persons,Comparator.comparingInt(Person::getAge));assertTrue(Arrays.equals(persons,newPerson[]{newPerson("Larry",18),newPerson("Harry",18),newPerson("James",20),newPerson("David",30)}));JDK的Collections工具类提供了排序方法,可以方便使用。 对于实现Comparable的类进行排序:
//Collections.sort对于实现Comparable的类进行排序List<String>names=asList("Larry","Harry","James","David");Collections.sort(names);assertEquals(names,asList("David","Harry","James","Larry"));提供Comparator进行排序:
//Collections.sort提供Comparator进行排序List<Person>persons2=asList(newPerson("Larry",18),newPerson("David",30),newPerson("James",20),newPerson("Harry",18));Collections.sort(persons2,Comparator.comparingInt(Person::getAge));assertEquals(persons2,asList(newPerson("Larry",18),newPerson("Harry",18),newPerson("James",20),newPerson("David",30)));反序:只是把List反过来,并不代表一定是按照大小顺序的:
//Collections.reverse反序names=asList("Larry","Harry","James","David");Collections.reverse(names);assertEquals(names,asList("David","James","Harry","Larry"));List接口有sort(Comparator<? super E> c)方法,可以实现对自身的排序,会影响自身的顺序。
//List.sort排序names=asList("Larry","Harry","James","David");names.sort(Comparator.naturalOrder());assertEquals(names,asList("David","Harry","James","Larry"));Stream提供了sorted()和sorted(Comparator<? super T> comparator)进行排序,会返回一个新的Stream。
//Stream.sorted排序names=asList("Larry","Harry","James","David");List<String>result=names.stream().sorted().collect(Collectors.toList());assertEquals(result,asList("David","Harry","James","Larry"));//Stream.sorted提供Comparator排序names=asList("Larry","Harry","James","David");result=names.stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList());assertEquals(result,asList("David","Harry","James","Larry"));对类的单字段进行排序很简单,只要提供形如:
Comparator.comparing(类名::属性getter)
的Comparator就行了。如果需要倒序,就需要:
Comparator.comparing(类名::属性getter).reversed()
或Comparator.comparing(类名::属性getter, Comparator.reverseOrder())。
具体代码使用(为了不破坏List的原有顺序,我们都使用Stream来操作):
//单字段排序-升序List<Person>personList=asList(newPerson("Larry",18),newPerson("David",30),newPerson("David",3),newPerson("James",20),newPerson("Harry",18));List<Person>personResult=personList.stream().sorted(Comparator.comparing(Person::getName)).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("David",30),newPerson("David",3),newPerson("Harry",18),newPerson("James",20),newPerson("Larry",18)));//单字段排序-倒序1personResult=personList.stream().sorted(Comparator.comparing(Person::getName).reversed()).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("Larry",18),newPerson("James",20),newPerson("Harry",18),newPerson("David",30),newPerson("David",3)));//单字段排序-倒序2personResult=personList.stream().sorted(Comparator.comparing(Person::getName,Comparator.reverseOrder())).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("Larry",18),newPerson("James",20),newPerson("Harry",18),newPerson("David",30),newPerson("David",3)));多字段其实也很方便,只需要用thenComparing进行连接就可以: Comparator.comparing(类名::属性一getter).thenComparing(类名::属性二getter) 具体代码使用例子如下:
//多字段排序-1升2升personResult=personList.stream().sorted(Comparator.comparing(Person::getName).thenComparing(Person::getAge)).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("David",3),newPerson("David",30),newPerson("Harry",18),newPerson("James",20),newPerson("Larry",18)));//多字段排序-1升2倒personResult=personList.stream().sorted(Comparator.comparing(Person::getName).thenComparing(Person::getAge,Comparator.reverseOrder())).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("David",30),newPerson("David",3),newPerson("Harry",18),newPerson("James",20),newPerson("Larry",18)));//多字段排序-1倒2升personResult=personList.stream().sorted(Comparator.comparing(Person::getName,Comparator.reverseOrder()).thenComparing(Person::getAge)).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("Larry",18),newPerson("James",20),newPerson("Harry",18),newPerson("David",3),newPerson("David",30)));//多字段排序-1倒2倒personResult=personList.stream().sorted(Comparator.comparing(Person::getName,Comparator.reverseOrder()).thenComparing(Person::getAge,Comparator.reverseOrder())).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("Larry",18),newPerson("James",20),newPerson("Harry",18),newPerson("David",30),newPerson("David",3)));感谢各位的阅读,以上就是“Java中Sorting知识点有哪些”的内容了,经过本文的学习后,相信大家对Java中Sorting知识点有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是本站,小编将为大家推送更多相关知识点的文章,欢迎关注!