一 .Map
public interface Map<K,V>
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。此接口哦取代了Dictionary类,后者完全是一个抽象类,而不是一个接口。
Map接口和Collection接口的区别
Map是双列的,而Collection是单列的Map的键唯一,而Collection的子体系的Set是唯一的Map集合的数据结构只针对键有效,跟值无关,而Collection集合的数据结构是针对元素有效
二 .下面先了解Map集合的基本功能,后面研究其常用的四个子类。
添加功能
V put(K key,V value)
添加元素,也可以有替换功能,如果键是第一次存储,就直接存储元素,返回null。如果键已经存在,那么就用值把以前的值替换掉,返回以前的值
删除功能
void clear()
移除所有的键值对元素
V remove(Object key)
根据键删除键值对元素,并把值返回
获取功能
Set<Map.Entry<K,V>> entrySet()
返回一个键值对的Set集合
V get(Object key)
根据键获取值
Set keySet():获取集合中所有键的集合
获取集合中所有键的集合
Collection values()
获取集合中所有值的集合
判断功能
boolean containsKey(Object key)
判断集合是否包含指定的键
boolean containsValue(Object value)
判断集合是否包含制定的值
boolean isEmpty()
判断集合是否为空
长度功能
int size()
获取集合中的键值对的对数
import java.util.Collection;import java.util.HashMap;import java.util.Map;import java.util.Set;public class MyTest1 {public static void main(String[] args) {HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("海绵宝宝",21);hashMap.put("章鱼哥",22);hashMap.put("派大星",23);hashMap.put("蟹老板",24);//当键已经存在时,再次存储就把旧值替换掉,返回以前的值Integer integer = hashMap.put("海绵宝宝", 25);//根据键删除键值对元素hashMap.remove(21);//判断集合是否包含指定的键hashMap.containsKey("派大星");//判断集合是否包含制定的值hashMap.containsValue(23);//返回一个键值对的Set集合Set entries = hashMap.entrySet();//根据键获取值hashMap.get("蟹老板");//返回集合中所有键的集合Set strings = hashMap.keySet();//获取集合中所有值的集合Collection<Integer> values = hashMap.values();//获取集合中键值对的对数int size = hashMap.size();//清空所有的键值对元素hashMap.clear();}}
三.Map集合的两种遍历方式
方式一
import java.util.HashMap;import java.util.Set;public class MyTest2 {public static void main(String[] args) {HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("海绵宝宝",21);hashMap.put("章鱼哥",22);hashMap.put("派大星",23);hashMap.put("蟹老板",24);Set<String> set = hashMap.keySet();for (String key : set) {System.out.println(key+" "+hashMap.get(key));}}}
方式二
import java.util.HashMap;import java.util.Map;import java.util.Set;public class MyTest3 {public static void main(String[] args) {HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("海绵宝宝",21);hashMap.put("章鱼哥",22);hashMap.put("派大星",23);hashMap.put("蟹老板",24);Set<Map.Entry<String, Integer>> entries = hashMap.entrySet();for (Map.Entry<String, Integer> entry : entries) {String key = entry.getKey();Integer value = entry.getValue();System.out.println(key+" "+value);}}}
两个的运行结果为:
派大星 23海绵宝宝 21章鱼哥 22蟹老板 24
四.Map接口下面常用的四个子类
HashMapLinkedHashMapTreeMapConcurrentHashMap
1.HashMap
底层是散列表+红黑树。初始容量为16,加载因子为0.75,每次扩容两倍。允许nul值null键l,存储无序线程非同步散列表容量大于64且链表大于8时,转成红黑树key的哈希值会与该值的高16位做异或操作,进一步增加随机性当散列表的元素大于容量 * 加载因子时,会在散列,每次扩容两倍
import java.util.HashMap;public class MyTest5 {public static void main(String[] args) {HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put("海绵宝宝",21);hashMap.put("章鱼哥",22);hashMap.put("派大星",23);hashMap.put("蟹老板",24);hashMap.put("蟹老板",999);System.out.println(hashMap);}}
运行结果为:
{派大星=23, 海绵宝宝=21, 章鱼哥=22, 蟹老板=999}
存取顺序不一致
2.LinkedHashMap
底层数据结构是散列表+红黑树+双向链表键的数据结构是链表+哈希表,链保证键有序,哈希表保证键唯一Map接口的哈希表和链接链表实现,具有可预知的迭代顺序。允许null值null键线程非同步提供插入顺序和访问顺序两种,访问顺序是符合LRU(最近最近未使用算法)的,一般用于扩展(默认是插入排序)。大多使用了HashMap的API,只不过在内部重写了某些方法,维护了双向链表
import java.util.LinkedHashMap;public class MyTest4 {public static void main(String[] args) {LinkedHashMap<String, Integer> linkedHashMap = new LinkedHashMap<>();linkedHashMap.put("郭杰瑞",34);linkedHashMap.put("角角",24);linkedHashMap.put("明明",27);linkedHashMap.put("木鱼水心",32);linkedHashMap.put("信誓旦旦",37);System.out.println(linkedHashMap);}}
运行结果为:
{郭杰瑞=34, 角角=24, 明明=27, 木鱼水心=32, 信誓旦旦=37}
可以看出存取顺序一致
3.TreeMap
底层是红黑树,保证了时间复杂度位log(n)可以对其进行排序,使用Comparable或者Comparator只要compare或者CompareTo认定该元素相等,那就相等线程非同步当自然排序(手动排序)元素不能为null
1.使用自然排序时,要求里面的元素实现了Comparable接口,重写了compareTo()方法。例如下面的一段代码,按照年龄对元素进行排序。
public class Student implements Comparable<Student>{private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic int compareTo(Student s ) {int num = this.age - s.getAge();int num2=num==0?pareTo(s.name):num;return num2 ;}}
import java.util.Map;import java.util.Set;import java.util.TreeMap;public class MyTest1 {public static void main(String[] args) {TreeMap<Student, String> treeMap = new TreeMap<>();treeMap.put(new Student("章鱼哥",23),"海绵宝宝");treeMap.put(new Student("熊大",24),"熊出没");treeMap.put(new Student("叶修",23),"全职高手");//遍历方式二Set<Map.Entry<Student, String>> entries = treeMap.entrySet();for (Map.Entry<Student, String> entry : entries) {Student key = entry.getKey();String value = entry.getValue();System.out.println(key.getAge()+" "+key.getName()+" "+value);}}}
运行结果为:
23 叶修 全职高手23 章鱼哥 海绵宝宝24 熊大 熊出没
2.使用比较器排序
public class Student{private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;} }
import java.util.Map;import java.util.Set;import java.util.TreeMap;public class MyTest1 {public static void main(String[] args) {TreeMap<Student, String> treeMap = new TreeMap<>();treeMap.put(new Student("章鱼哥",23),"海绵宝宝");treeMap.put(new Student("熊大",24),"熊出没");treeMap.put(new Student("叶修",23),"全职高手");//遍历方式一Set<Map.Entry<Student, String>> entries = treeMap.entrySet();for (Map.Entry<Student, String> entry : entries) {Student key = entry.getKey();String value = entry.getValue();System.out.println(key.getAge()+" "+key.getName()+" "+value);}}}
运行结果为:
23 叶修 全职高手17 天明 秦时明月24 熊大 熊出没23 章鱼哥 海绵宝宝
4.ConcurrentHashMap
底层是散列表+红黑树,支持高并发操作key和value都不能为空线程是安全的,利用CAS算法和部分操作上锁实现get方法是通常是非阻塞,无锁的。重写Node类,通过volatile修饰next来实现每次获取都是最新设置的值在高并发环境下,统计数据(size等)是没有意义的,因为在下一时刻size值就变化了。
五.HashMap和Hashtable的区别
HashMap:线程不安全,效率高,允许null值null键。HashTable:线程安全,效率低,不允许null值null键
六.集合之间的嵌套
HashMap嵌套HashMapHashMap嵌套ArrayListArrayList嵌套HashMap
HashMap嵌套HashMap
import java.util.HashMap;import java.util.Set;public class MyTest {public static void main(String[] args) {/* 基础班张三 20李四 22就业班王五 21赵六 23*///HashMap 嵌套 HashMapHashMap<String, Integer> jcMap = new HashMap<>();jcMap.put("张三",20);jcMap.put("李四",22);HashMap<String, Integer> jyMap = new HashMap<>();jyMap.put("王五",21);jyMap.put("赵六",23);HashMap<String, HashMap<String, Integer>> maxMap = new HashMap<>();maxMap.put("基础班",jcMap);maxMap.put("就业班",jyMap);Set<String> set = maxMap.keySet();for (String s : set) {System.out.println(s);HashMap<String, Integer> minMap = maxMap.get(s);Set<String> set1 = minMap.keySet();for (String s1 : set1) {System.out.println("\t"+s1+" "+minMap.get(s1));}}}}
HashMap嵌套ArrayList
import java.util.ArrayList;import java.util.HashMap;import java.util.Set;public class MyTest2 {public static void main(String[] args) {/***三国演义吕布周瑜笑傲江湖令狐冲林平之神雕侠侣郭靖杨过*/// HashMap 嵌套 ArrayListArrayList<String> sgList = new ArrayList<>();sgList.add("吕布");sgList.add("周瑜");ArrayList<String> xaList = new ArrayList<>();xaList.add("令狐冲");xaList.add("林平之");ArrayList<String> sdList = new ArrayList<>();sdList.add("郭靖");sdList.add("杨过");HashMap<String, ArrayList<String>> hashMap = new HashMap<>();hashMap.put("三国演义",sgList);hashMap.put("笑傲江湖",xaList);hashMap.put("神雕侠侣",sdList);Set<String> set = hashMap.keySet();for (String s : set) {System.out.println(s);ArrayList<String> list = hashMap.get(s);for (String s1 : list) {System.out.println("\t"+s1);}}}}
ArrayList嵌套HashMap
import java.util.ArrayList;import java.util.HashMap;import java.util.Set;public class MyTest3 {public static void main(String[] args) {//周瑜-- - 小乔//吕布-- - 貂蝉////郭靖-- - 黄蓉//杨过-- - 小龙女////令狐冲-- - 任盈盈//林平之-- - 岳灵珊//ArrayList 嵌套 HashMapHashMap<String, String> sgMap = new HashMap<>();sgMap.put("周瑜","小乔");sgMap.put("吕布","貂蝉");HashMap<String, String> sdMap = new HashMap<>();sdMap.put("郭靖","黄蓉");sdMap.put("杨过","小龙女");HashMap<String, String> xaMap = new HashMap<>();xaMap.put("令狐冲","任盈盈");xaMap.put("林平之","岳灵珊");ArrayList<HashMap<String, String>> maxList = new ArrayList<>();maxList.add(sgMap);maxList.add(sdMap);maxList.add(xaMap);for (HashMap<String, String> map : maxList) {Set<String> set = map.keySet();for (String s : set) {System.out.println(s+"---"+map.get(s));}System.out.println();}}}