Java自定义排序
Java中自定义排序可以通过实现Comparator接口或Comparable接口来完成。
关键:实现Comparator接口的关键在于重写compare()方法,Comparable接口的关键在于重写compareTo()方法。JDK中大部分的类都实现了Comparable接口,拥有compareTo方法。如Integer,String等。但是对于自己定义类,如果需要自定义排序,则要实现Comparable接口并重写compareTo()方法,若不重写就进行自定义排序,会报错。
方法:将实现好的接口作为参数传入Arrays.sort()中或Collections.sort()中即可。
上述两个静态方法都可以进行排序,简单区别:
1.Arrays.sort()方法可以对原始类型(基本数据类型)和对象类型进行排序,而Collections.sort()只能对List进行排序。
2.查看源码发现,Collections.sort()也是通过Arrays.sort()方法实现的
Comparator具体使用方法:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CustomSort {
public static void main(String args[]){
Integer numbers1[] = {32, 3, 321};
List<Integer> list1 = Arrays.asList(numbers1);
//注意list1中元素类型必须是对象类型,写原始类型会报错
Collections.sort(list1, new MyComparator2());
for (Integer integer : list1) {
System.out.print(integer+" ");
}
System.out.println("\n---------------");
//使用arrays.sort()方法自定义排序
Integer numbers2[] = {1,51,6,1,465,496,-156};
Arrays.sort(numbers2, new MyComparator2());
for (Integer integer : numbers2) {
System.out.print(integer+" ");
}
System.out.println("\n*************************");
Student2 st1 = new Student2(123, "Bob");
Student2 st2 = new Student2(122, "Bob");
Student2 st3 = new Student2(124, "Allen");
//使用collections.sort()方法
List<Student2> list3 = new ArrayList<>();
list3.add(st1);list3.add(st2);list3.add(st3);
Collections.sort(list3, new MyComparator2());
for (Student2 student : list3) {
System.out.print(student);
}
System.out.println("\n---------------");
Student2 ss1[] = {st1, st2, st3};
//使用Arrays.sort()方法
Arrays.sort(ss1, new MyComparator2());
for (Student2 student : ss1) {
System.out.print(student);
}
}
}
class MyComparator2 implements Comparator<Object>{
@Override
public int compare(Object o1, Object o2){
//如果两个都是整数才调用该比较方法
if(o1 instanceof Integer && o2 instanceof Integer){
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return -i1.compareTo(i2);
}
//如果两个都是student2类型
if(o1 instanceof Student2 && o2 instanceof Student2){
Student2 s1 = (Student2)o1;
Student2 s2 = (Student2)o2;
//先按名字字典序排序,再按学号升序排序
int t = s1.getName().compareTo(s2.getName());
if(t == 0){
return s1.getId().compareTo(s2.getId());
}else return t;
}
return 0;
}
}
//自定义一个学生类,然后对学生进行排序
class Student2{
Integer id;
String name;
public Student2(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "[id=" + id + ", name=" + name + "] ";
}
}
运行结果:
321 32 3
---------------
496 465 51 6 1 1 -156
*************************
[id=124, name=Allen] [id=122, name=Bob] [id=123, name=Bob]
---------------
[id=124, name=Allen] [id=122, name=Bob] [id=123, name=Bob]
Comparable具体使用方法:
public class TestComparable {
public static void main(String args[]){
Student3 st1 = new Student3(123, "Bob");
Student3 st2 = new Student3(122, "Bob");
Student3 st3 = new Student3(124, "Allen");
//使用Collections.sort()方法进行排序
List<Student3> list1 = new ArrayList<>();
list1.add(st1);list1.add(st2);list1.add(st3);
Collections.sort(list1);
for (Student3 student : list1) {
System.out.print(student);
}
System.out.println("\n-------------");
//使用Arrays.sort()方法进行排序
Student3 s[] = {st1, st2, st3};
Arrays.sort(s);
for (Student3 student : s) {
System.out.print(student);
}
}
}
//实现Comparable接口
class Student3 implements Comparable<Student3>{
Integer id;
String name;
public Student3(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "[id=" + id + ", name=" + name + "] ";
}
//重写compareTo方法,自定义排序规则
@Override
public int compareTo(Student3 stu){
//先按名字字典序排序,再按学号升序排序
int t = this.name.compareTo(stu.name);
if(t == 0){
return this.id.compareTo(stu.id);
}else return t;
}
}
运行结果:
[id=124, name=Allen] [id=122, name=Bob] [id=123, name=Bob]
-------------
[id=124, name=Allen] [id=122, name=Bob] [id=123, name=Bob]
弄懂Java中排序的一些使用方法后,手是不是有点痒。试试下面这个题目吧。
题目出处参考<kbd>《剑指offer》:把数组排成最小的数</kbd>
<kbd>题目描述
<kbd>输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。</kbd>
输入描述
<kbd>多组输入
每组测试样例第一行为n,表示数组有n个整数,接下来一行n个整数
</kbd>
输入描述
<kbd>每组输入输出一行,整个数组排成的最小的数字</kbd>
sample input
<kbd>5
6 2 87 15 2
3
3 32 321</kbd>
sample output
<kbd>1522687
321323</kbd>
source
<kbd>《剑指offer》:把数组排成最小的数</kbd>
</kbd>
起初可能会没有思路,但是仔细想想过后,你会发现这是一道排序题,通过自定义排序规则就可以做到排出来的数字最小。
思路:假设两个数m和n,试考虑m和n应该怎么排列才能使得m和n拼接的数字最小?这个应该很好办,无非就是两种拼接方式都试一遍,比较一下mn和nm的大小即可。这样一来,两个数扩展到n个数也是一样的。我们只需要两两进行拼接进行比较,知道最后全部比完,这也就相当于一个排序。
当mn < nm时,我们想要的是mn这种拼接方式,所以m应该排在n前面。而当mn = nm时,无论哪种方式都可以。同理当mn > nm时,我们定义n排在m前面。
那么问题来了,怎么进行拼接?很直观的可以想到两个数值拼接起来,但是这样是有可能溢出的。所以我们采用字符串拼接,把数字看成字符串,然后进行比较。下面代码中调用的是String自带的compareTo方法(按照字典序)。
示例代码:
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class OfferSort {
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int n;
while(sc.hasNext()){
n = sc.nextInt();
//输入
int arr[] = new int[n];
for(int i = 0; i < n; i++)
arr[i] = sc.nextInt();
//转化为字符串
String s[] = new String[arr.length];
for(int i = 0; i < arr.length; i++)
s[i] = String.valueOf(arr[i]);
//按照自定义的规则排序
Arrays.sort(s, new MyComparator5());
//组装答案并输出
String ans = "";
for (String str : s)
ans += str;
System.out.println(ans);
}
}
}
class MyComparator5 implements Comparator<Object>{
@Override
public int compare(Object o1, Object o2){
if(o1 instanceof String && o2 instanceof String){
String s1 = (String)o1;
String s2 = (String)o2;
String s3 = s1+s2;
String s4 = s2+s1;
int t = s3.compareTo(s4);
if(t > 0)//若s3>s4,即s1s2 > s2s1,所以我们s2排在s1的前面
return 1;
else if(t < 0)//s3<s4, 所以s1应该排在s2前面
return -1;
else return 0;
}
return 0;
}
}