Java的Set、Map和数组的自定义排序
Java的Set、Map和数组的自定义排序
该文章讲述下面三点并给出相应实例
- Set的三种自定义排序和遍历
- Map的三种自定义排序和遍历
- 数组的三种自定义排序
1.Set的三种自定义排序和遍历
这里的三种自定义排序分别是
-
实现Comparator接口的compare方法并传入构造函数
-
传入Lambda表达式作为函数接口的参数
-
以类名::静态方法名作为函数接口的参数
当然还有常用的第四种方法,让存储元素的类实现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 */