1.数组排序及list排序       


        在JAVA中对数组排序或list元素排序,JAVA提供了Arrays.sort()及Collections.sort(),使用者只要正确调用即可,不需要使用者自己写排序算法的实现。当然如果数据量大,并且要求效率高的话,还是需要自己选择适当排序算法的自己写代码实现。


         打开Collections.sort()源码,发现sort()重载了2次。

public static <T extends Comparable<? super T>> void sort(List<T> list) {
	Object[] a = list.toArray();
	Arrays.sort(a);
	ListIterator<T> i = list.listIterator();
	for (int j=0; j<a.length; j++) {
	    i.next();
	    i.set((T)a[j]);
	}
    }


public static <T> void sort(List<T> list, Comparator<? super T> c) {
	Object[] a = list.toArray();
	Arrays.sort(a, (Comparator)c);
	ListIterator i = list.listIterator();
	for (int j=0; j<a.length; j++) {
	    i.next();
	    i.set(a[j]);
	}
    }

       看源码知道Collections.sort()只对list类型进行排序,将list转换为数组,然后再用Arrays.sort()进行真正的排序。下面重点认识Arrays.sort()即可。

       看看Arrays.sort()进行了什么样的重载。

java stream对list中的map进行倒序排序 java list<map>排序_对象排序


 


      Arrays.sort()支持所有基本数据类型的排序(byte,char,short,int,float,double,long)、Object对象排序及自定义的对象排序(需要实现Comparable接口或传入一个Comparator比较器,下面将会讲解)。

       对于元素类型是基本数据类型的数组,排序很简单,只需将数组传给Arrays.sort()即可。

package sort;

import java.util.Arrays;

public class JavaSort {
	public static void main(String[] args) {
		int[] x={5,2,10,45,6,4,69};
		System.out.println("排序前......");
		System.out.println(Arrays.toString(x));
		Arrays.sort(x);//排序,默认是从小到大
		System.out.println("排序后......");
		System.out.println(Arrays.toString(x));
	}
}

运行结果
排序前......
[5, 2, 10, 45, 6, 4, 69]
排序后......
[2, 4, 5, 6, 10, 45, 69]


对象排序,则必须告诉JVM排序规则。

    

     如果你留意过Integer,Double,Long,String等这些类,会发现他们都实现了Comparable接口,Comparable接口定义如下

public interface Comparable<T> {
 public int compareTo(T o);
}

     

     Integer类中的compareTo()方法

public int compareTo(Integer anotherInteger) {
	int thisVal = this.value;
	int anotherVal = anotherInteger.value;
	return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
    }

两对象比较,前者<后者,返回-1;前者>后者,返回1;前者=后者,返回0.

   

     下面写个小例子看下,两个user比较,按照age排序,如果age相等就按照姓名(中文)的拼音顺序排序。由于这例子中涉及到中文按拼音顺序排序。所以先看个中文排序例子。

      中文按照拼音顺序排序。

package sort;

import java.text.Collator;
import java.util.Arrays;

public class JavaSort {
	public static void main(String[] args) {
		Collator cmp=Collator.getInstance(java.util.Locale.CHINA);//获得中文比较器
		String[] x={"张三","李四","赵五","孙六"};
		System.out.println("排序前......");
		System.out.println(Arrays.toString(x));
		Arrays.sort(x,cmp);//告诉Arrays.sort要按照cmp这个比较规则进行比较
		System.out.println("排序后......");
		System.out.println(Arrays.toString(x));
		
	}
}

运行结果


排序前......
[张三, 李四, 赵五, 孙六]
排序后......
[李四, 孙六, 张三, 赵五]


好了,已经知道中文按照拼音顺序排序的方法了,那么下面来看看user按照age排序,如果age相等,就按照name(中文)排序的小例子.


package sort;

import java.text.Collator;
import java.util.Locale;

public class User implements Comparable<User>{

	private String name;
	private int age;
	
	public User(String name,int age){
		this.name=name;
		this.age=age;
	}
	
	@Override
	public int compareTo(User o) {
		int c1=this.age<o.getAge()?-1:(this.age==o.getAge()?0:1);//age compare
		if(c1!=0) return c1;//如果年龄不相等,则返回比较结果,姓名就不需要比较了
		return Collator.getInstance(Locale.CHINA).compare(this.name, o.getName());//返回姓名比较的结果
	}

	/**
	 * 为了方便打印user对象,重写toString
	 */
	public String toString(){
		return "{"+this.name+"  "+this.age+"}";
	}
	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;
	}

}


package sort;

import java.text.Collator;
import java.util.Arrays;

public class JavaSort {
	public static void main(String[] args) {
		User[] users={
				new User("张三",20),
				new User("李四",25),
				new User("赵五",18),
				new User("孙六",18)
		};
		System.out.println("排序前......");
		System.out.println(Arrays.toString(users));
		Arrays.sort(users);
		System.out.println("排序后......");
		System.out.println(Arrays.toString(users));
		
	}
}

运行结果

 排序前......
[{张三  20}, {李四  25}, {赵五  18}, {孙六  18}]
排序后......
[{孙六  18}, {赵五  18}, {张三  20}, {李四  25}]

 

上面的user类直接实现了Comparable接口,所以user对象可以进行比较。但是我们开发中,可能会遇到这种情况,比如User类是一个

JavaBean(POJO),初期是没有实现Comparable接口的,现在有需求需要user对象可以进行比较排序,先按照age排序,再按照name排序,不允许对User类进行修改。为了解决这种情况,JAVA提供了Comparator接口,定义如下

public interface Comparator<T> {
    int compare(T o1, T o2);
    boolean equals(Object obj);
}

        如果你细心,就会发现我上面贴出的Arrays.sort()重载的截图,发现有个sort(T[] a, Comparator<? super T> c);这个方法就是允许你传入一个自己定义的比较器。

package sort;


public class User {

	private String name;
	private int age;
	
	public User(String name,int age){
		this.name=name;
		this.age=age;
	}
	
	
	/**
	 * 为了方便打印user对象,重写toString
	 */
	public String toString(){
		return "{"+this.name+"  "+this.age+"}";
	}
	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;
	}

}


package sort;

import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;

public class UserComparator implements Comparator<User>{

	@Override
	public int compare(User u1, User u2) {
		int c1=u1.getAge()<u2.getAge()?-1:(u1.getAge()==u2.getAge()?0:1);//年龄比较
		if(c1!=0) return c1;
		return Collator.getInstance(Locale.CHINA).compare(u1.getName(), u2.getName());//返回姓名比较的结果
	}

}


package sort;

import java.text.Collator;
import java.util.Arrays;

public class JavaSort {
	public static void main(String[] args) {
		User[] users={
				new User("张三",20),
				new User("李四",25),
				new User("赵五",18),
				new User("孙六",18)
		};
		System.out.println("排序前......");
		System.out.println(Arrays.toString(users));
		Arrays.sort(users,new UserComparator());//这里的比较器也可以写成匿名类,不需要在写一个UserComparator类了
		System.out.println("排序后......");
		System.out.println(Arrays.toString(users));
		
	}
}

运行结果
 排序前......
[{张三  20}, {李四  25}, {赵五  18}, {孙六  18}]
排序后......
[{孙六  18}, {赵五  18}, {张三  20}, {李四  25}]

2.Map排序

       Map在实际开发中,会经常被使用到,特别是它的子类HashMap。HashMap是无序存放,就是说遍历得到的结果是随机的,无序的。那能不能对Map进行排序呢?JAVA中提供了TreeMap类,它是有序存放的,按集合中的key排序。先看看TreeMap例子

package sort;

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class TreeMapTest {
	public static void main(String[] args) {
		Map<String,String> map=new TreeMap<String,String>();
		map.put("b", "李四");
		map.put("c", "赵五");
		map.put("a", "张三");
		map.put("d", "孙六");
		Iterator<String> it=map.keySet().iterator();
		while(it.hasNext()){
			String key=(String)it.next();
			System.out.println(key+"  "+map.get(key));
		}
	}
}

运行结果

a  张三
b  李四
c  赵五
d  孙六

   

 

        TreeMap可以对集合中的key排序,如果key是自己写的一个类呢?那么这时就需要new TreeMap()时,传入构造器。比如

Map<User,String> useMap=new TreeMap<User,String>(new UserComparator());

            TreeMap默认的是按key排序,那能否按value值排序呢?如果对Map的子类有所了解的同学,都知道map中的key-value都是保存在一个Entry类中,那key排序或者value排序,都可以通过Map.Entry<K,V>结合list进行排序。

          

package sort;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class TreeMapTest {
	public static void main(String[] args) {
		Map<String,String> map=new TreeMap<String,String>();
		map.put("b", "李四");
		map.put("c", "赵五");
		map.put("a", "张三");
		map.put("d", "孙六");
		List<Map.Entry<String,String>> mapList=new ArrayList<Map.Entry<String,String>>(map.entrySet());
		Collections.sort(mapList, new Comparator<Map.Entry<String,String>>(){
			@Override
			public int compare(Entry<String, String> o1,
					Entry<String, String> o2) {
				Collator cmp=	Collator.getInstance(Locale.CHINA);//中文按照拼音排序比较器
				return cmp.compare(o1.getValue(), o2.getValue());//如果想按key排序,改成getKey()就OK了
			}
			
		});
		for(Map.Entry<String, String> m:mapList){
			System.out.println(m.getKey()+"  "+m.getValue());
		}
		
	}
}

运行结果

b  李四
d  孙六
a  张三
c  赵五

    对HashMap,HashTable,LinkedHashMap等Map的子类其实都可以这样处理的。下面把上面程序的TreeMap改成 HashMap,按Key排序。


package sort;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class TreeMapTest {
	public static void main(String[] args) {
		Map<String,String> map=new HashMap<String,String>();
		map.put("b", "李四");
		map.put("c", "赵五");
		map.put("a", "张三");
		map.put("d", "孙六");
		List<Map.Entry<String,String>> mapList=new ArrayList<Map.Entry<String,String>>(map.entrySet());
		Collections.sort(mapList, new Comparator<Map.Entry<String,String>>(){
			@Override
			public int compare(Entry<String, String> o1,
					Entry<String, String> o2) {
				return o1.getKey().compareTo(o2.getKey());//如果想按value排序,改成getValue()就OK了
			}
			
		});
		for(Map.Entry<String, String> m:mapList){
			System.out.println(m.getKey()+"  "+m.getValue());
		}
		
	}
}

运行结果

a  张三
b  李四
c  赵五
d  孙六