JAVA Map架构和API介绍: Map,Map.Entry,AbstractMap,SortedMap,NavigableMap,Dictionary.
首先我们看看Map架构:
首先我们看看Map架构:
如上图:
Map是映射接口,Map中存储的内容是键值对(key-value).
AbstractMap是继承与Map的抽象类,它实现了Map中的大部分API.其它Map的实现类可以通过继承AbstractMap来减少
重复编码.
SortedMap 是继承于Map的接口.SortedMap中的内容是排序的键值对, 排序的方法是通过比较器(Comparator).
NavigableMap 是继承于SortedMap的接口. 相比于SortedMap,NavigableMap有一系列的导航方法;如"获取大于/等于某对象
的键值对"等等.
TreeMap 继承于AbstractMap,且实现了NavigableMap接口;因此,TreeMap中的内容是"有序的键值对"!
HashMap 继承于AbstractMap, 但没有实现NavigableMap接口;因此,HashMap的内容是"键值对,但不保证次序"!
Hashtable 虽然不是继承于AbstractMap,但它继承于Dictionary(Dictionary也是键值对接口),而且也实现Map接口;
因此,Hashtable的内容也是"键值对,也不保证次序". 但和HashMap相比,Hashtable是线程安全的,而且它支持通过
Enumeration去遍历.
WeakHashMap 继承于AbstractMap. 它和HashMap的键类型不同,WeakHashMap的键是"弱键".
http://www.jb51.net/article/42768.htm
1. Map
语法: public interface Map<K,V>{}
Map 是一个键值对(key-value)映射接口. Map映射中不能包含重复的键; 每个键最多只能映射到一个值.
Map 接口提供三种collection视图, 允许以键集,值集或者键-值映射关系集形式查看某个映射的内容.
Map 映射顺序. 有些实现类,可以明确保证其顺序,如TreeMap; 另一些映射实现则不保证顺序,如HashMap类.
Map 的实现类应该提供2个"标准的"构造方法: 第一个, void(无参数)构造方法,用于创建映射; 第二个,带
有单个Map类型参数的构造方法,用于创建一个与其参数具有相同键-值映射关系的新映射. 实际上, 后一个
构造方法允许用户复制任意映射,生成所需类的一个等价映射.
Map提供接口分别用于返回 键集,值集或键-值映射关系集.
entrySet() 用于返回键-值集的Set集合
keySet() 用于返回键集的Set集合
values() 用于返回值集的Collection集合
get(k key) 用于根据键获取值
因为Map中不能包含重复的键;每个键最多只能映射到一个值.所以, 键-值集,键集都是Set,值集是Collection.
Map接口功能
1.1 添加功能
put(K key,V value):添加元素.
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存储,就用值把以前的值替换掉,返回以前的值
1.2 删除功能
void clear(): 移除所有的键值对元素
remove(K key): 根据键删除键值对元素,并把值返回,没有就返回null.
1.3 判断功能
boolean containsKey(K key): 判断集合是否包含指定的键
boolean containsValue(V value): 判断集合是否包含指定的值
boolean isEmpty(): 判断集合是否为空
1.4 长度功能
int size(): 返回集合中的键值对的对数
2.Map集合的遍历
例如:
Map<String,String> map = new HashMap<String,String>();
map.put("1","张三");
map.put("2","李四");
map.put("3","王五");
2.1 键找值
Set<> set = map.keySet();
for(String key : set){
String value = map.get(key);
System.out.println(key+ "----"+value);
}
结果:
1----张三
2----李四
3----王五
Map<String,String> map = new HashMap<>();
map.put("001","张三");
map.put("002","李四");
map.put("003","王五");
Set<String> set = map.keySet();
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
String key = iterator.next();
String value = map.get(key);
System.out.println(key+"----"+value);
}
结果:
001----张三
002----李四
003----王五
2.2 键值对对象找键和值
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"----"+value);
}
结果:
1----张三
2----李四
3----王五
Map<String,String> map = new HashMap<>();
map.put("001","张三");
map.put("002","李四");
map.put("003","王五");
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<String, String> m = iterator.next();
String key = m.getKey();
String value = m.getValue();
System.out.println(key+"----"+value);
}
结果:
001----张三
002----李四
003----王五
3. LinkedHashMap
LinkedHashMap: 是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序.
由哈希表保证键的唯一性
由链表保证键的有序(存储和取出的顺序一致)
4.Hashtable和HashMap的区别?
Hashtable: 线程安全,效率低. 不允许null键和null值
HashMap: 线程不安全,效率高. 允许null键和null值
5. TreeMap
public class test {
public static void main(String[] args) throws Exception {
/*
* 需求 :"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)
*
* 分析:
* A:定义一个字符串(可以改进为键盘录入)
* B:定义一个TreeMap集合
* 键:Character
* 值:Integer
* C:把字符串转换为字符数组
* D:遍历字符数组,得到每一个字符
* E:拿刚才得到的字符作为键到集合中去找值,看返回值
* 是null:说明该键不存在,就把该字符作为键,1作为值存储
* 不是null:说明该键存在,就把值加1,然后重写存储该键和值
* F:定义字符串缓冲区变量
* G:遍历集合,得到键和值,进行按照要求拼接
* H:把字符串缓冲区转换为字符串输出
*
*/
//1.定义一个字符串(可以改进为键盘录入)
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个字符串:");
//String line = scanner.next(); //获取输入的字符串
String line = "aababcabcdabcde";
//2.定义一个TreeMap集合
TreeMap<Character,Integer> treeMap = new TreeMap<Character,Integer>();
//3.把字符串字符数组
char[] chars = line.toCharArray();
//遍历字符数组得到每一个字符
for (char aChar : chars) {
//4. 拿遍历的字符作为键到集合中去找值
Integer integer = treeMap.get(aChar);
//5. 如果是null,说明该键不存在,就把该字符作为键,1作为值存储
if (integer==null){
treeMap.put(aChar,1);
}else {
//6. 如果不为null,说明该键存值,就把值加1,然后重新存储该键和值
integer++;
treeMap.put(aChar,integer);
}
}
//7.定义字符串缓存变量
StringBuilder stringBuilder = new StringBuilder();
//8. 遍历集合,得到键和值,进行按要求拼接
Set<Character> characters = treeMap.keySet();
for (Character character : characters) {
Integer integer = treeMap.get(character);
stringBuilder.append(character).append("(").append(integer).append(")");
}
//9 . 把字符串缓存区转换为字符串输出
String string = stringBuilder.toString();
System.out.println(string);
}
}
结果:a(5)b(4)c(3)d(2)e(1)
6. Map转换为List类型
6.1 Map通过List的构造方法转换为List类型
Map<String,String> map = new HashMap<>();
map.put("001","张三");
map.put("002","李四");
map.put("003","王五");
//获取map键的List集合
List keyList = new ArrayList(map.keySet());
System.out.println(keyList);
结果: [001, 002, 003]
//获取map值的List集合
List valueList = new ArrayList(map.values());
System.out.println(valueList);
结果: [张三, 李四, 王五]
//获取map键值的List集合
List entryList = new ArrayList(map.entrySet());
System.out.println(entryList);
结果: [001=张三, 002=李四, 003=王五]
6.2 Map通过List的addAll()方法转换为List集合
Map<String,String> map = new HashMap<>();
map.put("001","张三");
map.put("002","李四");
map.put("003","王五");
//获取map键的List集合
List keyList = new ArrayList();
keyList.addAll(map.keySet());
System.out.println(keyList);
结果: [001, 002, 003]
//获取map值的List集合
List valueList = new ArrayList();
valueList.addAll(map.values());
System.out.println(valueList);
结果: [张三, 李四, 王五]
//获取map键值的List集合
List entryList = new ArrayList();
entryList.addAll(map.entrySet());
System.out.println(entryList);
结果: [001=张三, 002=李四, 003=王五]
7. Map排序
7.1.1 通过key对Map排序(排序需要对Map的key进行频繁的操作,第一中方式是通过比较器<comparator>来实现):
1>.通过key对Map升序排序:
Map<String,String> map = new HashMap<>();
map.put("001","张三");
map.put("005","李四");
map.put("003","王五");
List<Map.Entry<String, String>> entryList = new ArrayList<Map.Entry<String, String>>(map.entrySet());
Collections.sort(entryList, new Comparator<Map.Entry<String, String>>(){
@Override
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
//升序排序
return o1.getKey().compareTo(o2.getKey());
}
});
for (Map.Entry<String, String> stringStringEntry : entryList) {
String key = stringStringEntry.getKey();
String value = stringStringEntry.getValue();
System.out.println(key+"------"+value);
}
001------张三
003------王五
005------李四
2>.通过key对Map降序排序:
Map<String,String> map = new HashMap<String,String>();
map.put("001","张三");
map.put("005","李四");
map.put("003","王五");
List<Map.Entry<String,String>> entryList = new ArrayList<Map.Entry<String, String>>(map.entrySet());
Collections.sort(entryList, new Comparator<Map.Entry<String,String>>() {
@Override
public int compare(Map.Entry<String,String> o1, Map.Entry<String,String> o2) {
//降序排序
return o2.getKey().compareTo(o1.getKey());
}
});
for (Map.Entry<String, String> stringStringEntry : entryList) {
String key = stringStringEntry.getKey();
String value = stringStringEntry.getValue();
System.out.println(key+"------"+value);
}
结果:
005------李四
003------王五
001------张三
7.1.2 通过key对Map排序(第二种方法是通过SortedMap,但必须实现Comparable接口):
1>.通过key对Map降序排序:
Map<String,String> map = new TreeMap<String,String>(new Comparator<String>() { //等价于 SortedMap<String,String> map = new TreeMap<String,String>(new Comparator<String>() {
@Override
public int compare(String str1, String str2) {
//降序排序
return str2.compareTo(str1);
}
});
map.put("001","张三");
map.put("005","李四");
map.put("003","王五");
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"----"+value);
}
结果:
005----李四
003----王五
001----张三
2>.通过key对Map升序排序:
Map<String,String> map = new TreeMap<String,String>(new Comparator<String>() { //等价于 SortedMap<String,String> map = new TreeMap<String,String>(new Comparator<String>() {
@Override
public int compare(String str1, String str2) {
//升序排序
return str1.compareTo(str2);
}
});
map.put("001","张三");
map.put("005","李四");
map.put("003","王五");
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"-------"+value);
}
结果:
001-------张三
003-------王五
005-------李四
7.1.3 对value的Map进行排序(慎用,测试这个排序不太准确)
1> 通过value对Map升序排序:
Map<String,String> map = new TreeMap<String,String>();
map.put("a", "ddddd");
map.put("c", "bbbbb");
map.put("d", "aaaaa");
map.put("b", "ccccc");
List<Map.Entry<String, String>> entryList = new ArrayList<Map.Entry<String, String>>(map.entrySet());
Collections.sort(entryList, new Comparator<Map.Entry<String, String>>(){
@Override
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
//升序排序
return o1.getValue().compareTo(o2.getValue());
}
});
for (Map.Entry<String, String> stringStringEntry : entryList) {
String key = stringStringEntry.getKey();
String value = stringStringEntry.getValue();
System.out.println(key+"------"+value);
}
结果:
d------aaaaa
c------bbbbb
b------ccccc
a------ddddd
8. 对Map的复制
JAVA中提供了很多方法都可以实现对一个Map的复制,但是那些方法不见得会时时同步.简单的说,就是一个Map发
生变化,而复制的那个依然保持原样.
语法: Map copyMap = Collections.synchronizedMap(map);
例如:
Map<String,String> map = new HashMap<String,String>();
map.put("001","张三");
map.put("005","李四");
map.put("003","王五");
System.out.println("map: "+map);
Map<String, String> map1 = Collections.synchronizedMap(map);
System.out.println("map1: "+map1);
结果:
map: {001=张三, 003=王五, 005=李四}
map1: {001=张三, 003=王五, 005=李四}
9. 创建一个空的Map
如果这个map被置为不可用,可以通过以下实现
Map<Object, Object> map = Collections.emptyMap();
相反,我们用到的时候,就可以直接使用(如下):
map= new HashMap<>();
10. List,Set,Map判断两个对象值相等的标准
10.1 List
方法: 通过equals()方法比较返回true即可.
例如1:
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
List list1 = new ArrayList();
list1.add("张三");
list1.add("李四");
list1.add("王五");
boolean equals = list.equals(list1);
System.out.println(equals);
结果: true
例如2:
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
List list1 = new ArrayList();
list1.add("张三");
list1.add("李四");
list1.add("王五s");
boolean equals = list.equals(list1);
System.out.println(equals);
结果: false
10.2 HashSet
方法: 先比较两个对象的hashCode()方法返回的值是否相等,如果不相等就认为两个对象是不等的,
如果两个对象的hashCode相等就继续调用equals()方法进一步判断两个对象是否相等,如果equals()
方法返回true认为两个对象相等,返回false认为两个对象不相等.
例如:
Set<String> set = new HashSet<String>();
set.add("张三");
set.add("李四");
set.add("王五");
set.add("赵六");
Set<String> set1 = new HashSet<String>();
set1.add("张三");
set1.add("李四");
set1.add("王五");
set1.add("赵六");
int i = set.hashCode();
int ii = set1.hashCode();
System.out.println(i+"========="+ii);
System.out.println(i==ii);
boolean equals = set.equals(set1);
System.out.println(equals);
if(set.hashCode()==set1.hashCode()){
boolean equalsd = set.equals(set1);
System.out.println(equals);
}else{
System.out.println(false);
}
结果:
3697463=========3697463
true
true
true
10.3 TreeSet
方法: 两个对象通过CompareTo()方法比较是否返回0;如果返回0,则认为相等,否则不相等.