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;
	}
}
全部评论

相关推荐

10-07 23:57
已编辑
电子科技大学 Java
八街九陌:博士?客户端?开发?啊?
点赞 评论 收藏
分享
头像
11-18 16:08
福州大学 Java
影流之主:干10年不被裁,我就能拿别人一年的钱了,日子有盼头了
点赞 评论 收藏
分享
点赞 1 评论
分享
牛客网
牛客企业服务