今天在搞JAVA容器类题目的时候,碰到了一道对MAP容器的Value值排序的问题,额。。。当时无从下手,然后慌得一批,两天没看就将学的JAVA容器忘得一干二净,在这里做一下详细的学习和整理,ORZMAP博客大佬。
首先在这里进行理论储备,对MAP容器有一个大致的了解:
Map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等。
TreeMap:基于红黑树(Red-Black tree)的 NavigableMap 实现,该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
HashMap的值是没有顺序的,它是按照key的HashCode来实现的,对于这个无序的HashMap我们要怎么来实现排序呢?参照TreeMap的value排序。
Map.Entry返回Collections视图。
所以,涉及到对MAP进行的排序类的操作,我们需要使用Treemap来完成。
下面开始我们的重头戏(主要是对Value值排序的整理),其中会穿插,MAP.ENTRY的解释,以及SCANNER容易出现的一些错误,以及MAP的多种遍历方法。
一、key值排序
看了很多博客,以及百度后,发现key值排序的最长用方法有最基本的两种,个人推荐使用第一种方法(原因吗。。。反正别人告诉我的是更符合设计模式)。
下面给出两种方法的基本模板:
第一种:
package ceshi;
import java.util.*;
import java.math.*;
class StringComparator implements Comparator<String>
{
public int compare(String a,String b)
{
return a.compareTo(b);
}
}
public class Main {
public static void main(String[] args) {
Map<String,String> map=new TreeMap(new StringComparator());//在定义MAP时同时规定排序方式
map.put("b", "ccccc");
map.put("d", "aaaaa");
map.put("c", "bbbbb");
map.put("a", "ddddd");
for(String k:map.keySet())
{
System.out.println(k);
}
}
}
//数据输出
//a
//b
//c
//d
第二种:
package ceshi;
import java.util.*;
import java.math.*;
public class Main {
public static void main(String[] args) {
Map<String,String> map=new TreeMap(new Comparator<String>()
{
public int compare(String a,String b)
{
return a.compareTo(b);
}
}
map.put("b", "ccccc");
map.put("d", "aaaaa");
map.put("c", "bbbbb");
map.put("a", "ddddd");
for(String k:map.keySet())
{
System.out.println(k);
}
}
}
//数据输出
//a
//b
//c
//d
其实可以看出,上述的两种方法其实是一种原理的两种实现方式,通过Comparator进行对TreeMap的排序方式的定义,至于Comparator方法的讲解,这里不再给出。
这里给出的是Map的多种遍历方法。
二.Value值排序
首先说明的是MAP容器是无法自身通过Value值进行排序的,所以这里我们需要借助List,与MAP.Entry接口进行对MAP容器的Value值进行排序。这里我们首先理解一下MAP.ENTRY接口map.entry详解。
注意,Map.entrySet(),返回的是set,而MAP.ENTRY<K,V>.可类似于一种对象类型。
一定要在了解map.entry后再去了解以下代码:
package ceshi;
import java.util.*;
import java.math.*;
//对学生成绩进行排序
class DoubleComparator implements Comparator<Map.Entry<String, Double>>
{
public int compare(Map.Entry<String, Double> a,Map.Entry<String, Double> b)
{
if(a.getValue()>b.getValue()) return 1;
else if(a.getValue()<b.getValue()) return -1;
else return 0;
}
}
public class Main {
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
Map<String,Double> map=new TreeMap<String,Double>();
int n=Integer.parseInt(scan.nextLine());
for(int i=0;i<n;i++)
{
String str=scan.nextLine();
String[] t=str.split(" ");
map.put(t[0], Double.valueOf(t[1]));
}
List<Map.Entry<String, Double>> list=new ArrayList<Map.Entry<String, Double>>(map.entrySet());//定义泛型并进行初始化
Collections.sort(list, new DoubleComparator());
for(Map.Entry<String, Double> k: list)
{
System.out.println(k.getValue());
}
}
}
//测试数据
//TOM 21
//JJ 99
//GG 11
//GB 100
//样例输出
//11.0
//21.0
//99.0
//100.0
这里点出两个问题:
1、在上述代码中 注意int n 的读入方式,为什么要这么读入?
nextInt只读书数字,而不会读入数据中的回车符,这就影响了下面String 的读入 更多关于读入的细则点这里
2、collection.sort与array.sort究竟有什么区别?