浅谈java自定义排序(多维排序)(数组,列表,set,map)

前言:

说到排序,不禁想起了Arrays.sort()方法,不过它只有一种顺序,即升序。可是我们做的题目中要求可能并不是升序,或者说其元素也不一定是一维的,那么怎么办?

数组:

              若元素是一维的,直接Arrays.sort(),但是如果想要倒序怎么办?emm。。。bingo,倒着输出不就完了嘛。

              若元素是二维的以及以上的,那必须得自己定义规则了,方法有两种,1.自定义容器排序的规则,(重写cmp 继承comparator接口)2.自定义类的排序规则,使元素本身具有比较性。(自身类继承comparable接口)

代码如下:



import java.util.Arrays;
import java.util.Comparator;

public class Array {

	static class Coordinate{
		int x;
		int y;
		public Coordinate(int x,int y){
			this.x=x;
			this.y=y;
		}
	} 
	
	static class MyComparator1 implements Comparator<Object>
    //让容器自身具备比较性,自定义比较器。
	{	
		public int compare(Object o1, Object o2) {
			Coordinate a=(Coordinate) o1;
			Coordinate b=(Coordinate) o2;
			if(a.x==b.x)
				return a.y-b.y;//小于优先级高一点
			else
			{
				//System.out.println(a.x+" "+b.x+" "+(a.x-b.x));
				return a.x-b.x;
                //返回true a的优先级低 b排在其前面  反之,a的优先级高,排在前面
			}
		}
		
	}
	static class MyComparator2 implements Comparator<Coordinate>
    //让容器自身具备比较性,自定义比较器。
	{	
		public int compare(Coordinate o1, Coordinate o2) {
			Coordinate a=o1;
			Coordinate b=o2;
			if(a.x==b.x)
				return b.y-a.y;//大于优先级高
			else
				return b.x-a.x;
		}
		
	}
	
	static void init(Coordinate a[])
	{
		for(int i=0;i<a.length-1;i++)
			a[i]=new Coordinate(i,i+1);
		a[a.length-1]=new Coordinate(0,-1);
	}
	static void output2(Coordinate a[])
	{
		for(int i=0;i<a.length;i++)
			System.out.print("("+a[i].x+" "+a[i].y+")"+" ");
		System.out.println();
	}
	

	static class Coordinate3 implements Comparable<Coordinate3>//让元素自身具备比较性
	{
		int x;
		int y;
		public Coordinate3(int x,int y){
			this.x=x;
			this.y=y;
		}
		@Override
		public int compareTo(Coordinate3 o) {
			
			if(this.x==o.x)
				return this.y-o.y;//升序
			else
				return this.x-o.x;
		}
	} 
	
	static void init3(Coordinate3 a[])
	{
		for(int i=0;i<a.length-1;i++)
			a[i]=new Coordinate3(i,i+1);
		a[a.length-1]=new Coordinate3(0,-1);
	}
	static void output3(Coordinate3 a[])
	{
		for(int i=0;i<a.length;i++)
			System.out.print("("+a[i].x+" "+a[i].y+")"+" ");
		System.out.println();
	}
	

	//元素一维
	static void output(int a[],boolean flag)
	{
		if(flag)//升序
			for(int i=0;i<a.length;i++)
				System.out.print(a[i]+" ");
		else//降序
			for(int i=a.length-1;i>=0;i--)
				System.out.print(a[i]+" ");
		System.out.println();
	}
	
	
	
	
	public static void main(String[] args) {
		int	a[]={1,4,3,2,5};
		Arrays.sort(a);
		System.out.println("元素一维正序排列:");
		output(a,true);//true 正序
		System.out.println("元素一维倒序排列:");//额,倒序输出就OK了
		output(a,false);
		
		System.out.println("元素多维Comparator方法");
		Coordinate a2[]=new Coordinate[5];
		init(a2);
		
		System.out.println("原始:");
		output2(a2);
		
		Arrays.sort(a2,new MyComparator1());//升序
		System.out.println("排序1升序后");
		output2(a2);
		
		Arrays.sort(a2,new MyComparator2());//降序
		System.out.println("排序2降序后");
		output2(a2);
		
		System.out.println("元素多维Comparable方法");
		Coordinate3 a3[]=new Coordinate3[5];//使类具有排序功能,继承
		init3(a3);
		
		System.out.println("原始:");
		output3(a3);
		
		
		Arrays.sort(a3);
		System.out.println("排序后");
		output3(a3);

	}

}

输出:

元素一维正序排列:
1 2 3 4 5 
元素一维倒序排列:
5 4 3 2 1 
元素多维Comparator方法
原始:
(0 1) (1 2) (2 3) (3 4) (0 -1) 
排序1升序后
(0 -1) (0 1) (1 2) (2 3) (3 4) 
排序2降序后
(3 4) (2 3) (1 2) (0 1) (0 -1) 
元素多维Comparable方法
原始:
(0 1) (1 2) (2 3) (3 4) (0 -1) 
排序后
(0 -1) (0 1) (1 2) (2 3) (3 4) 

               

链表:

               链表,我最常用的是ArrayList,LinkedList也用过,不过大多是使用queue,或stack时用的,emm,下面以ArrayList为例进行分析:

               其实一维的话,需要调用Collections.sort();

               多维的话,还是上面两种方法:1.自定义容器排序的规则,(重写cmp 继承comparator接口)2.自定义类的排序规则,使元素本身具有比较性。(自身类继承comparable接口)

代码如下:



import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;


public class List {

	//元素一维
	static void output(ArrayList<Integer> list)
	{
		for(int i=0;i<list.size();i++)
			System.out.print(list.get(i)+" ");
		System.out.println();
	}
	//多维
	static class Coordinate2{
		int x;
		int y;
		public Coordinate2(int x,int y){
			this.x=x;
			this.y=y;
		}
	} 
	
	static class MyComparator implements Comparator<Coordinate2>
    //让容器自身具备比较性,自定义比较器。
	{	
		public int compare(Coordinate2 o1, Coordinate2 o2) {
			
			if(o1.x==o2.x)
				return o1.y-o2.y;//小于优先级高一点
			else
				return o1.x-o2.x;
        //返回true a的优先级低 b排在其前面  反之,a的优先级高,排在前面
		}
		
	}
	
	
	static void init2(ArrayList<Coordinate2> list)
	{
		for(int i=0;i<4;i++)
			list.add(new Coordinate2(i,i+1));
		list.add(new Coordinate2(0,-1));
		
	}
	static void output2(ArrayList<Coordinate2> list)
	{
		for(int i=0;i<list.size();i++)
			System.out.print("("+list.get(i).x+" "+list.get(i).y+")"+" ");
		System.out.println();
	}
	

	static class Coordinate3 implements Comparable<Coordinate3>//让元素自身具备比较性
	{
		int x;
		int y;
		public Coordinate3(int x,int y){
			this.x=x;
			this.y=y;
		}
		@Override
		public int compareTo(Coordinate3 o) {
			
			if(this.x==o.x)
				return this.y-o.y;//升序
			else
				return this.x-o.x;
		}
	} 
	
	static void init3(ArrayList<Coordinate3> list)
	{
		for(int i=0;i<4;i++)
			list.add(new Coordinate3(i,i+1));
		list.add(new Coordinate3(0,-1));
		
	}
	static void output3(ArrayList<Coordinate3> list)
	{
		for(int i=0;i<list.size();i++)
			System.out.print("("+list.get(i).x+" "+list.get(i).y+")"+" ");
		System.out.println();
	}
	
	
	public static void main(String[] args) {
		ArrayList<Integer> list=new ArrayList<Integer>();
		list.add(1);
		list.add(3);
		list.add(2);
		list.add(5);
		list.add(4);
		
		System.out.println("原始:");
		output(list);
		
		Collections.sort(list);
		System.out.println("元素一维正序排列:");
		output(list);//true 正序
		
		
		System.out.println("元素多维Comparator方法");
		ArrayList<Coordinate2> list2=new ArrayList<Coordinate2>();
		init2(list2);
		
		System.out.println("原始:");
		output2(list2);
		
		Collections.sort(list2,new MyComparator());//升序
		System.out.println("排序升序后");
		output2(list2);
		
		System.out.println("元素多维Comparable方法");
		ArrayList<Coordinate3> list3=new ArrayList<Coordinate3>();
        //使类具有排序功能
		init3(list3);
		
		System.out.println("原始:");
		output3(list3);
		
		Collections.sort(list3);
		System.out.println("排序后");
		output3(list3);

	}
}

输出:

原始:
1 3 2 5 4 
元素一维正序排列:
1 2 3 4 5 
元素多维Comparator方法
原始:
(0 1) (1 2) (2 3) (3 4) (0 -1) 
排序升序后
(0 -1) (0 1) (1 2) (2 3) (3 4) 
元素多维Comparable方法
原始:
(0 1) (1 2) (2 3) (3 4) (0 -1) 
排序后
(0 -1) (0 1) (1 2) (2 3) (3 4) 

set:

            set:没有重复元素的集合,hashset:性质和set一样,但是比set要快一点,treeSet:元素唯一且有序。

            一维的直接TreeSet。(对不起,TreeSet就是可以为所欲为~)

            多维的也是那两种方法,继承comparable使类自排序,继承comparator写自己的cmp,需要强调一点的是当同时存在以上两种情况时,后者起决定性作用。

代码如下:



import java.util.Comparator;
import java.util.TreeSet;
import java.util.Iterator;

public class Set {

	//元素一维
	static void output(TreeSet<String> set)
	{
		Iterator<String> iterator=set.iterator();
		while(iterator.hasNext())
		{
			String next=iterator.next();
			System.out.print(next+" ");
		}
		System.out.println();
	}
	//多维
	static class Coordinate2{
		int x;
		int y;
		public Coordinate2(int x,int y){
			this.x=x;
			this.y=y;
		}
	} 
	
	static class MyComparator implements Comparator<Coordinate2>//让容器自身具备比较性,自定义比较器。
	{	
		public int compare(Coordinate2 o1, Coordinate2 o2) {
			
			if(o1.x==o2.x)
				return o2.y-o1.y;//大于优先级高一点
			else
				return o2.x-o1.x;//相当于重载小于号,o2.x<o1.x
		}
		
	}
	
	
	static void init2(TreeSet<Coordinate2> set)
	{
		set.add(new Coordinate2(1,0));
		set.add(new Coordinate2(2,0));
		set.add(new Coordinate2(3,0));
		set.add(new Coordinate2(1,-1));
		set.add(new Coordinate2(2,-1));
		set.add(new Coordinate2(3,-1));
		set.add(new Coordinate2(1,-1));
		set.add(new Coordinate2(2,-1));
		set.add(new Coordinate2(3,-1));
	}
	static void output2(TreeSet<Coordinate2> set)
	{
		Iterator<Coordinate2> iterator=set.iterator();
		while(iterator.hasNext())
		{
			Coordinate2 C= iterator.next();
			System.out.print("("+C.x+" "+C.y+")"+" ");
		}
		System.out.println();
	}
	

	static class Coordinate3 implements Comparable<Coordinate3>//让元素自身具备比较性
	{
		int x;
		int y;
		public Coordinate3(int x,int y){
			this.x=x;
			this.y=y;
		}
		@Override
		public int compareTo(Coordinate3 o) {
			
			if(this.x==o.x)
				return o.y-this.y;//降序
			else
				return o.x-this.x;
		}
	} 
	
	static void init3(TreeSet<Coordinate3> set)
	{
		set.add(new Coordinate3(1,0));
		set.add(new Coordinate3(2,0));
		set.add(new Coordinate3(3,0));
		set.add(new Coordinate3(1,-1));
		set.add(new Coordinate3(2,-1));
		set.add(new Coordinate3(3,-1));
		set.add(new Coordinate3(1,0));//元素唯一
		set.add(new Coordinate3(2,0));
		set.add(new Coordinate3(3,0));
	}
	static void output3(TreeSet<Coordinate3> set)
	{
		Iterator<Coordinate3> iterator=set.iterator();//迭代器
		while(iterator.hasNext())
		{
			Coordinate3 C= iterator.next();
			System.out.print("("+C.x+" "+C.y+")"+" ");
		}
		System.out.println();
	}
	
	
	public static void main(String[] args) {
		TreeSet<String> set=new TreeSet<String>();
		set.add("a");
		set.add("e");
		set.add("c");
		set.add("c");//元素唯一
	
		System.out.println("元素一维正序排列:");
		output(set);//true 正序
		
		
		System.out.println("元素多维Comparator方法//降序");
		TreeSet<Coordinate2> set2=new TreeSet<Coordinate2>(new MyComparator());
		init2(set2);
		output2(set2);
		
		System.out.println("元素多维Comparable方法//降序");
		TreeSet<Coordinate3> set3=new TreeSet<Coordinate3>();//使类具有排序功能,继承
		init3(set3);
		output3(set3);

	}
}

输出结果:

元素一维正序排列:
a c e 
元素多维Comparator方法//降序
(3 0) (3 -1) (2 0) (2 -1) (1 0) (1 -1) 
元素多维Comparable方法//降序
(3 0) (3 -1) (2 0) (2 -1) (1 0) (1 -1) 

map:

map的中文意思是映射,这也是其之本质,她的每一个元素都有 (key,value)键值对组成。

其之特点是键值唯一,一一对应。

java中常见的map:

HashMap(无序)

最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null(多条会覆盖);允许多条记录的值为 Null。非同步的。

TreeMap(有序)

能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。 

Hashtable

与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。 

LinkedHashMap

保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。 

常用API: 注意EntrySet和KeySet的区别

clear() 从 Map 中删除所有映射
remove(Object key) 从 Map 中删除键和关联的值
put(Object key, Object value) 将指定值与指定键相关联
putAll(Map t) 将指定 Map 中的所有映射复制到此 map
entrySet() 返回 Map 中所包含映射的 Set 视图。Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素
keySet() 返回 Map 中所包含键的 Set 视图。删除 Set 中的元素还将删除 Map 中相应的映射(键和值)
values() 返回 map 中所包含值的 Collection 视图。删除 Collection 中的元素还将删除 Map 中相应的映射(键和值)
get(Object key) 返回与指定键关联的值
containsKey(Object key) 如果 Map 包含指定键的映射,则返回 true
containsValue(Object value) 如果此 Map 将一个或多个键映射到指定值,则返回 true
isEmpty() 如果 Map 不包含键-值映射,则返回 true
size() 返回 Map 中的键-值映射的数目

一般我们排序的时候用TreeMap多一点,所以下面以TreeMap为例进行说明

代码如下:



import java.util.Iterator;
import java.util.TreeMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Map解析 {

	static void init(TreeMap<String,Integer> map)
	{
		map.put("z", 6);
		map.put("y", 6);
		map.put("y", 7);
		map.put("a", 9);
		map.put("b", 100);
		map.put("c", 100);
		
	}

	static void output(TreeMap<String,Integer> map)
	{
		Iterator<String> iterator= map.keySet().iterator();
		while(iterator.hasNext())//不能在其遍历时改变其值,不然会报错
		{
			String next=iterator.next();
			System.out.print("("+next+","+map.get(next)+")"+" ");
		}
		System.out.println();		
	}
	
	static void output2(List<Map.Entry<String, Integer>> list)
	{
		Iterator<Entry<String, Integer>> iterator= list.iterator();//遍历速度最快
		while(iterator.hasNext())//不能在其遍历时改变其值,不然会报错
		{
			Entry<String, Integer> next=iterator.next();
			System.out.print("("+next.getKey()+","+next.getValue()+")"+" ");
		}
		System.out.println();		
	}
	
	public static void main(String[] args) {
		TreeMap<String,Integer> map=new TreeMap<String, Integer>();
		init(map);
		System.out.println("原始升序");
		output(map);
		
		System.out.println("继承comparator,写cmp比较器比较");
        System.out.println("方法一,转化为list,然后集合排序");
		System.out.println("排序规则:value值越大,优先级越高,越排在前面,value相同,key值越低,越排在前面");
		List<Map.Entry<String, Integer>> list=new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
		//通过ArrayList将Map.Entry<String, Integer>为list,
		//集合排序
		Collections.sort(list,new Comparator<Map.Entry<String, Integer>>(){
		//构造cmp Comparator<object>
			public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2)             {
				if(o1.getValue()==o2.getValue())
					return o1.getKey().compareTo(o2.getKey());//相当于小于运算符
				else
					return o2.getValue()-o1.getValue();
				
			}
			
		});
		output2(list);
		
		System.out.println("方法二,不用转化list,直接应用cmp,仅适用于TreeMap,(类似于TreeSet)逆序输出");
		TreeMap<String,Integer> map2=new TreeMap<String, Integer>(new Comparator<String>(){
			public int compare(String o1, String o2) {
				return o2.compareTo(o1);
			}
			
		});
		init(map2);
		output(map2);
		
	}

}

输出结果:

原始升序
(a,9) (b,100) (c,100) (y,7) (z,6) 
继承comparator,写cmp比较器比较
排序规则:value值越大,优先级越高,越排在前面,value相同,key值越低,越排在前面
(b,100) (c,100) (a,9) (y,7) (z,6) 
方法二,不用转化list,直接应用cmp,仅适用于TreeMap,(类似于TreeSet)逆序输出
(z,6) (y,7) (c,100) (b,100) (a,9) 
 

小结:

。。。

到这里,终于写完了!!!

后天就要蓝桥杯了,希望能用的上。

猜你喜欢

转载自blog.csdn.net/Look_star/article/details/88735135