1. 首先关于map排序分为java8之前的,和之后的。也分为按照key和按照value的。也分为按照默认排序和自己的排序器的,下面一一说明。
2. 一般排序按照key的话,一般key都是Integer和String,用TreeMap就可以了。
3. 首先上面已经说了,按照key排序的话,其实直接用TreeMap挺好的。
4. 首先是本次例子用的类(此类实现了Comparable接口。实际上下面有些事不需要实现的。因为有的是自己又另外加的选择器。我会指出来。)。这算是准备工作,为了能看懂下面的例子。
class Pet implements Comparable
{
String name;
int old;
public Pet(String name, int old)
{
this.name = name;
this.old = old;
}
public String toString()
{
return "name: "+name+",old: "+old;
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return old-((Pet)o).old;
}
}
然后是map的填充:
Pet p1 = new Pet("dog",2);
Pet p2 = new Pet("cat",5);
Pet p3 = new Pet("pig",3);
Pet p4 = new Pet("wolf",1);
Map<String, Pet> map = new HashMap<String,Pet>();
//Map<String, Pet> map = new TreeMap<String,Pet>();
map.put("d", p1);
map.put("c", p2);
map.put("p", p3);
map.put("w", p4);
4. 首先是原来的一般做法,按照key排序:
4.1. 此处的Map是一定要知道类型的。是不能像前面遍历(另一篇文章)哪样为了追求普适性不用泛型。
4.2. 这里出现了Map.Entry类,可以看出来他是Map的内部类。因为原来Map的遍历用到iterator的时候还需要回到map把value取出来。但是现在用Entry不用了。更方便。Java8里面加了按照key和value排序,排序也更方便了。
4.3 思路很简单,就是把Map按照Map.Entry取出来,放到List里面,然后借助Collectins的sort进行排序。当然,此时需要自己在Pet类外部实现一个泛型是Map.Entry的Compator比较器。此时Pet是没必要实现Comparable的。也没有用。因为Pet自己实现属于按照Pet的内部排序,而此时需要的是Map.Entry。
4.4 当然,比较器类可以是外部类,也可以是内部类。个人倾向于内部类。因为那是专门针对每一个类的。一般就只会用一次。
//根据原来的java,Value
public static Map compareByValue(Map map)
{
if(map==null||map.isEmpty())
return null;
ArrayList<Map.Entry<String, Pet>> list = new ArrayList<Map.Entry<String,Pet>>
(map.entrySet());
Collections.sort( list,new MapValueComparator());
Map<String,Pet> returnMap = new LinkedHashMap<String,Pet>();
for(Map.Entry<String, Pet> entry: list)
{
returnMap.put(entry.getKey(), entry.getValue());
}
return returnMap;
}
//比较器类2
class MapValueComparator implements Comparator<Map.Entry<String, Pet>>{
@Override
public int compare(Entry<String, Pet> o1, Entry<String, Pet> o2) {
// TODO Auto-generated method stub
return o1.getValue().old-o2.getValue().old;
}
}
5. 按照key,原来的java方法:
5.1. 思路很简单,就是从Map里面取出来,放到TreeMap里面就行。如果可以,在一开始读入的时候就放到TreeMap里面也未尝不可。这里只是为了展示排序方法这么做。
5.2.TreeMap里面有个参数,就是排序器Compator,其实你不加这个参数,默认的是按照Key排序。前提是key本身是可排序的。
5.3. 这里的Comparator用的就是内部类。仅仅为了展示一下。
//根据原来的java,key
public static Map compareByKey(Map map)
{
if(map==null||map.isEmpty())
{
return null;
}
//内部类的实现方式。
Map<String,Pet> returnMap = new TreeMap<String,Pet>((new MapSort()).new MapKeyComparator());
returnMap.putAll(map);
return returnMap;
}
//比较器类,只是用的是内部类。
class MapKeyComparator implements Comparator<String>{
public int compare(String p1, String p2) {
return p1.compareTo(p2);
}
}
Java8中Map.Entry的新方法:
6. 按照key:
6.1. 这是看到一个外国大神的博客写的。感觉很厉害,排序和遍历都很厉害。用了很多原来没有用过的技巧。虽然代码很短。
6.2. 其实也很简单,就是map提取Entry的list之后转化成流(string()),然后把流排序按照传入的Comparator排序。而Map.Entry的静态方法里面ComparingByKey()等四个方法都是返回Comparator(记得当时看API的时候还纳闷为什么返回Comparator)。当然,这要求Value或者key可排序,如果不可,就自己定义Compartor传进去。这和上面其实并无二致,只是用的方式不一样。
6.3. 还有一点,就是其实上面的传入Comparator时也可以用这些静态方法。
6.4. 最后,关于Collectors,和Arrays,Collections差不多,可以自己看API.
//根据key:java新增comparingByKey()
public static void sortByKey(Map map)
{
//System.out.println("sortByKey: ");
List<Map.Entry<String, Pet>> compareByValue = (List<Entry<String, Pet>>) map
.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toList());
compareByValue.forEach(System.out::println);
//System.out.println("sortByKey: end");
}
7. 按照value:
//根据value:java新增comparingByValue()
public static void sortByValue(Map map)
{
System.out.println("sortByValue: ");
List<Map.Entry<String, Pet>> compareByValue = (List<Entry<String, Pet>>) map
.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toList());
compareByValue.forEach(System.out::println);
System.out.println("sortByValue: end");
}
8. 传入参数的一个例子
8.1. 用的是Lamd表达式。
//根据key:java新增comparingByKey()
public static void sortByKey2(Map map)
{
System.out.println("sortByKey2: ");
List<Map.Entry<String, Pet>> compareByValue = (List<Entry<String, Pet>>) map
.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue((Pet p1,Pet p2)->{
return p1.name.length()-p2.name.length();
}))
.collect(Collectors.toList());// java.lang.String cannot be cast to com.map.Pet
compareByValue.forEach(System.out::println);
System.out.println("sortByKey2: end");
}