Java的Set、Map和数组的自定义排序

Java的Set、Map和数组的自定义排序

该文章讲述下面三点并给出相应实例

  1. Set的三种自定义排序和遍历
  2. Map的三种自定义排序和遍历
  3. 数组的三种自定义排序

1.Set的三种自定义排序和遍历

这里的三种自定义排序分别是

  1. 实现Comparator接口的compare方法并传入构造函数

  2. 传入Lambda表达式作为函数接口的参数

  3. 以类名::静态方法名作为函数接口的参数

当然还有常用的第四种方法,让存储元素的类实现Comparabel接口的comparaTo(Object)函数,不过这里不再阐述。

这里的三种遍历集合的方式是

​ 1. 使用迭代器遍历set集合

​ 2. 使用forEach函数用Lambda表达式实现遍历集合

​ 3. 使用forEach函数用类名::静态方法名实现遍历集合

下面以重载String的排序为例,将默认的字典序改为按字符串长度排序。

使用第一种方法自定义排序

package learn;
import java.util.*;
class EachInterface{
	static void fuc(String key) {
		System.out.println(key);
	}
}
class compare implements Comparator{ //第一种方式所需的接口实现类
	public int compare(Object _a,Object _b) {
		String a=(String)_a;
		String b=(String)_b;
		return a.length()-b.length();
	}
}
public class Learn {

	public static void main(String[] args) {
		TreeSet<String> mmp=new TreeSet<String>(new compare());//自定义排序的第一种方式
		mmp.add("abccc");
		mmp.add("dch2");
		mmp.add("qwe");
		/*遍历的第一种方式*/
		Iterator it=mmp.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
		System.out.println("===================");
		
		/*遍历的第二种方式*/
		mmp.forEach( (a)->{System.out.println(a);}	);
		System.out.println("===================");
		
		/*遍历的第三种方式*/
		mmp.forEach(EachInterface::fuc);
		
	}
	
}

/* 输出: qwe dch2 abccc =================== qwe dch2 abccc =================== qwe dch2 abccc */

使用第二种方法自定义排序

package learn;
import java.util.*;
public class Learn {

	public static void main(String[] args) {
		TreeSet<String> mmp=new TreeSet<String>( (_a,_b)->{
			String a=(String)_a;
			String b=(String)_b;
			return a.length()-b.length();
		});
	}
}

使用第三种方式

package learn;
import java.util.*;
class FucRefer{
	static public int compare(Object _a,Object _b) {
		String a=(String)_a;
		String b=(String)_b;
		return a.length()-b.length();
	}
}
public class Learn {

	public static void main(String[] args) {
		TreeSet<String> mmp=new TreeSet<String>(FucRefer::compare);	
	}
}



2.Map的三种自定义排序和遍历

自定义排序方法跟前面的set相同,只是遍历的时候不同。

package learn;
import java.util.*;
class EachRefer{
	static void fuc(String key,Integer value) {
		System.out.println("key:"+key+" values:"+value);
	}
}
class compare implements Comparator{
	public int compare(Object _a,Object _b) {
		String a=(String)_a;
		String b=(String)_b;
		return a.length()-b.length();
	}
}
class FucRefer{
	static public int compare(Object _a,Object _b) {
		String a=(String)_a;
		String b=(String)_b;
		return a.length()-b.length();
	}
}
public class Learn {

	public static void main(String[] args) {
        /*第一种自定义排序*/
		TreeMap<String,Integer> mmp=new TreeMap<String,Integer>(new compare());
        /*第三种自定义排序*/
// TreeMap<String,Integer> mmp=new TreeMap<String,Integer>(FucRefer::compare);
        /*第二种自定义排序*/
// TreeMap<String,Integer> mmp=new TreeMap<String,Integer>( (_a,_b)->{
// String a=(String)_a;
// String b=(String)_b;
// return a.length()-b.length();
// });
		mmp.put("dch",1);
		mmp.put("qwee",2);
		mmp.put("lqyyyy",3);
// mmp.add(1);
		Set entrySet=mmp.entrySet();
		
		
		/*遍历方法一 使用了迭代器*/
		Iterator it=entrySet.iterator();
		while(it.hasNext()) {
			Map.Entry<String, Integer> pair=(Map.Entry<String, Integer>)it.next();
			System.out.println("key:"+pair.getKey()+" values:"+pair.getValue());
		}
		System.out.println("===================");
		
		
		/*遍历方式二 使用forEach 传入一个lambda表达式*/
		mmp.forEach( (key,value)-> System.out.println("key:"+key+" values:"+value));
		
		System.out.println("===================");
		
		/*遍历方式三 使用forEach 传入一个方法引用*/
		mmp.forEach(EachRefer::fuc);	
	}
	
}
/* 输出: key:dch values:1 key:qwee values:2 key:lqyyyy values:3 =================== key:dch values:1 key:qwee values:2 key:lqyyyy values:3 =================== key:dch values:1 key:qwee values:2 key:lqyyyy values:3 */



3.数组的自定义排序

我们以普通数组为例,使用Arrays.sort成员函数进行排序

我们先来看下java的API开发文档中队sort怎么解释

所以我们这里讲述的三种方法分别是

​ 1.实现Comparator的compare方法

​ 2.使用Lambda表达式作为比较器

​ 3.使用类名::静态方法名的方式作为比较器

这里我们在c++中常常使用的pair类为例,我们实现一个pair类,并对之进行自定义排序

package learn;
import java.util.*;
class pair{
	public int first,second;
	public pair(){}
	public pair(int first,int second) {this.first=first;this.second=second;}
}
class compare implements Comparator{
	public int compare(Object _a,Object _b) {
		pair a=(pair)_a;
		pair b=(pair)_b;
		if(a.first!=b.first) return a.first-b.first;
		else	return a.second-b.second;
	}
}
class FucRefer{
	static public int cmp(pair a,pair b) {
		if(a.first!=b.first) return a.first-b.first;
		return a.second-b.second;
	}
}
public class Learn {
	public static void main(String[] args) {
		pair[] p=new pair[5];
		p[0]=new pair(1,2);
		p[1]=new pair(0,2);
		p[2]=new pair(1,1);
		p[3]=new pair(3,4);
		p[4]=new pair(0,10);
		
		/*第一种方法*/
		Arrays.sort(p,new compare());
		
		/*第二种方法*/
// Arrays.sort(p,(a,b)->{
// if(a.first!=b.first) return a.first-b.first;
// return a.second-b.second;
// } );
		
		/*第三种方法*/
		//Arrays.sort(p,FucRefer::cmp);
        
		/*增强for 循环输出*/
		for(pair pp :p) {
			System.out.println("first:"+pp.first+",second:"+pp.second);
		}
	}
}
/* 输出: first:0,second:2 first:0,second:10 first:1,second:1 first:1,second:2 first:3,second:4 */




彩蛋–实现对pair的”小于”号进行重载“

这个地方是瞎聊,可略过。

之所以对”小于“打引号,是因为java中不存在对小于号重载。(更扯淡的一点是java 进行元素之间的比较时竟然不是判断返回时true或false,而是判断是否为小于0,等于0,大于0。这与c++一点都步不一样,c++所以的自定义排序返回的都是bool类型哎)

set,map,甚至数组中,在使用sort进行排序时,默认是调用储存元素的compareTo函数(这与c++的较为相似,c++默认是用less()比较器,其中less函数采用 < 符号返回bool 类型)

每次要按照某一规则进行排序都要传入一个比较器是不是觉得很麻烦。有没有像c++里的重载小于号一样的方法呢?

Java提供了自然排序,自然排序要求所排序的元素必须实现Comparable接口,并重写compareTo方法,这样就会有自定义规定的默认排序。

下面来对自定义的pair类型为例,实现comparable接口的compareTo比较器

package learn;
import java.util.*;
class pair implements Comparable{
	public int first,second;
	public pair(){}
	public pair(int first,int second) {this.first=first;this.second=second;}
	public int compareTo(Object _b) {
		pair a=(pair)this;
		pair b=(pair)_b;
		if(a.first!=b.first) return a.first-b.first;
		return a.second-b.second;
	}
}
public class Learn {
	public static void main(String[] args) {
		pair[] p=new pair[5];
		p[0]=new pair(1,2);
		p[1]=new pair(0,2);
		p[2]=new pair(1,1);
		p[3]=new pair(3,4);
		p[4]=new pair(0,10);
		Arrays.sort(p);
		
		/*增强for 循环输出*/
		for(pair pp :p) {
			System.out.println("first:"+pp.first+",second:"+pp.second);
		}
	}
}
/* 输出: first:0,second:2 first:0,second:10 first:1,second:1 first:1,second:2 first:3,second:4 */
全部评论

相关推荐

10-19 10:28
已编辑
西南石油大学 后端工程师
团孝子已上线feeling:面了很多家公司,能感受到目前只有小公司+外包喜欢问八股。大厂虽然也问八股,但是是从实习、项目中进行提问,并且大厂会问很深,面试官也会对你的回答进行思考➕追问,所以准备大厂面试前一定要备好相关资料。对于算法,我做的是codetop前100+力扣hot100+力扣高频150,面试中实感hot100就足够,基本上只要是hot100就秒答。对于项目和八股,我做的也是烂大街的星球项目,八股则是看小林和问ai,自己也写了很多技术博客和画了很多思维导图,并且自己也尝试用嘴巴说出来,不只停留于纸面。运气也很重要,必须要让面试官/HR看到简历才行,所以建议投递时间是下午两点。tl:第一岗位9.9&nbsp;投递9.10&nbsp;一面(一面评价:最近见过最强的大三,结束五分钟后约二面,都晚上九点了不下班吗)9.11&nbsp;二面(三道算法a出两道,反问评价:经验不够等横向,我实习生要啥经验)9.21挂(实习时间过短+其他原因,想要一年实习的,为什么不招个正职)第二岗位10.10投递10.11约面(主管打电话,说看到我之前投递记录了想要我挂qa职进去干后端,同意)10.14&nbsp;一面(无八股,主动说确实很强,意愿很强)10.16&nbsp;oc其余,友邦,东软,东华,惠择,用友oc已拒京东测开一面挂(投后端被测开捞)腾讯测试已拒(投后端被测开捞)ps:表扬惠择的主管面,没怎么问技术(可能是一面面试官沟通过了),全程一起讲大道理,解答了心中很多疑惑,也告诉我以面试官角度来看怎么选候选人,如果可以下次一定选惠择
HeaoDng:美团好像可以触发一面通
点赞 评论 收藏
分享
迷茫的大四🐶:价格这么低都能满了?
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务