1 Map<K,V>接口
1.1 特点
- 双列集合一个元素包含俩值
- Key不可以重复,Value可以重复
- Key和Value一一对应
- Key和Value可以时任意类型
1.2 常用方法
public V put(K key, V value): 不重复返回null,重复返回value
public static void main(String[] args) {Map<String, Integer> persons = new HashMap<>();persons.put("张三",19);Integer out1 = persons.put("李四", 20);Integer out2 = persons.put("李四", 30);System.out.println(out1);//不重复返回nullSystem.out.println(out2);//重复返回原来的value=20System.out.println(persons);//{李四=30, 张三=19}}
public V remove(Object Key):指定键,删除键值对,返回删除键对应的值,键不存在则返回null
public static void main(String[] args) {Map<String, Integer> persons = new HashMap<>();persons.put("张三",19);persons.put("李四", 20);Integer out1 = persons.remove("张三");System.out.println(persons);//{李四=20}System.out.println(out1);//19Integer out2 = persons.remove("王五");System.out.println(out2);//null}
public V get(Object Key):通过键来获取值
public static void main(String[] args) {Map<String, Integer> persons = new HashMap<>();persons.put("张三",19);System.out.println(persons.get("张三"));//19System.out.println(persons.get("李四"));//null}
public boolean containsKey(Object Key):键是否存在
public static void main(String[] args) {Map<String, Integer> persons = new HashMap<>();persons.put("张三",19);System.out.println(persons.containsKey("张三"));//trueSystem.out.println(persons.containsKey("李四"));//false}
1.3 遍历Map集合
方法1:遍历键找值法
public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();map.put("张三",19);map.put("李四",20);map.put("王五",21);//1. 取出Map的所有key存在Set中Set<String> set = map.keySet();//2.1 while遍历set,获取key,map.get获取valueIterator<String> it = set.iterator();while(it.hasNext()){String key = it.next();Integer value = map.get(key);System.out.println(key + " " + value);}//2.2 foreach法遍历for(String key: set){System.out.println(key + " " + map.get(key));}}
方法2: Entry键值对对象
Map接口中有一个内部接口Entry
作用:Map一创建,就在Map中创建一个Entry对象,用来记录键和值,得到二者的映射关系。(相当于结婚证)
- Set<Map.Entry<K, V>> entrySet() 把Map集合的多个Entry对象取出存在Set集合中。
- 遍历Set集合,获取每个Entry对象。
- getKey()获取Key,getValue()获取Value。
public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();map.put("张三",19);map.put("李四",20);map.put("王五",21);//1. 取出Map的所有entry对象存在Set中Set<Map.Entry<String, Integer>>set = map.entrySet();//2.1 while遍历set,获取entry,再分别getKey和ValueIterator<Map.Entry<String, Integer>> it = set.iterator();while(it.hasNext()){Map.Entry<String, Integer> entry = it.next();String key = entry.getKey();Integer value = entry.getValue();System.out.println(key + " " + value);}//2.2 foreach法遍历for(Map.Entry<String, Integer> entry: set){System.out.println(entry.getKey() + " " + entry.getValue());}}
2 Map接口的实现类—— HashMap
2.1 特点
- 底层是哈希表(JDK1.8后:数组+链表/红黑树) 查询快
- 无序集合,存取无序
2.2 存储自定义类型键值
注意:因为Map集合要保证Key是唯一的,所以作为Key的元素必须重写hashCode方法和equals方法,从而保证Key的唯一性。
public static void main(String[] args) {Map<Person, Integer> map1 = new HashMap<Person, Integer>();map1.put(new Person("李四",10),170);map1.put(new Person("李四",10),180);System.out.println(map1);//重写前输出:{Person{name='李四', age=10}=180, Person{name='李四', age=10}=170}//重写后输出:{Person{name='李四', age=10}=180}}
3 HashMap的子类——LinkedHashMap
3.1 特点
- 底层是哈希表+链表 保证迭代顺序
- 有序集合,存取有序
3.2 使用示例
public static void main(String[] args) {HashMap<String, Integer> map1 = new HashMap<String, Integer>();map1.put("a",1);map1.put("c",3);map1.put("b",2);System.out.println(map1);//存和取顺序不同 {a=1, b=2, c=3}LinkedHashMap<String, Integer> map2 = new LinkedHashMap<>();map2.put("a",1);map2.put("c",3);map2.put("b",2);System.out.println(map2);//存和取顺序相同{a=1, c=3, b=2}}
4 Map接口的实现类——Hashtable
4.1 Hashtable的特点
- 键和值都不可以为空。
- 最早的双列集合,JDK1.0就有。
- 它是单线程的,同步的,线程安全,速度慢。
- 底层是一个哈希表。
- 和vector(ArrayList)一样再JDK1.2后被HashMap取代了。
- Hashtable的子类Properties集合是唯一一个和IO流结合的集合。【仍活跃】
4.2 示例
public static void main(String[] args) {Hashtable<String,String> ht = new Hashtable<>();HashMap<String, String> hm = new HashMap<>();hm.put(null,null);hm.put("a",null);hm.put(null,"b");System.out.println(hm);//{null=b, a=null}
// ht.put(null,null);
// 报错:java.lang.NullPointerException}
5 Map集合练习
5.1 统计字符出现次数
遍历字符串:charAt加索引遍历 / toCharArray转为数组
for(int i = 0; i < str.length(); i++) —> str.charAt(i)
for(char c: str.toCharArray()) —> c
public static void main(String[] args) {Scanner sc = new Scanner(System.in);String str = sc.next();Map<Character, Integer> map = new HashMap<>();char[] strArray = str.toCharArray();for (int i = 0; i < strArray.length; i++) {if(!map.containsKey(strArray[i])){map.put(strArray[i],1);}else{int value = map.get(strArray[i]);map.put(strArray[i],++value);}}System.out.println(map);}
5.2 斗地主升级版-玩家牌有序
public static void main(String[] args) {//1. 准备牌面String[] colors = {"♥","♠","♦","♣"};String[] nums = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};HashMap<Integer, String> pocker = new HashMap<>();pocker.put(0,"BK");pocker.put(1,"SK");int count = 2;for(String num: nums){for(String color: colors){pocker.put(count++,color+num);}}System.out.println(pocker);//2. 洗牌:打乱编号Set<Integer> set = pocker.keySet();ArrayList<Integer> list = new ArrayList<>();list.addAll(set);Collections.shuffle(list);ArrayList<Integer> left = new ArrayList<>();ArrayList<Integer> p1 = new ArrayList<>();ArrayList<Integer> p2 = new ArrayList<>();ArrayList<Integer> p3 = new ArrayList<>();for (int i = 0; i < pocker.size(); i++) {Integer p = list.get(i);if(i>=51){left.add(p);}else{if(i%3 == 0){p1.add(p);}else if(i%3 == 1){p2.add(p);}else{p3.add(p);}}}//3. 发牌:对编号排序 取出标号对应的值Collections.sort(p1);Collections.sort(p2);Collections.sort(p3);Collections.sort(left);ArrayList<String> player1 = new ArrayList<String>();ArrayList<String> player2 = new ArrayList<String>();ArrayList<String> player3 = new ArrayList<String>();ArrayList<String> dipai = new ArrayList<String>();for(Integer i : p1){player1.add(pocker.get(i));}for(Integer i : p2){player2.add(pocker.get(i));}for(Integer i : p3){player3.add(pocker.get(i));}for(Integer i : left){dipai.add(pocker.get(i));}//4. 看牌System.out.println(player1);System.out.println(player2);System.out.println(player3);System.out.println(dipai);}
6 JDK9对集合添加的优化
Java9中添加了几种集合工厂方法,更方便创建少量元素的集合、map实例。新的List、Set、Map的静态工厂方法可以更方便地创建集合的不可变实例。
使用前提:集合中存储的元素个数已经确定,不再改变时使用
注意:
- 只适用于List、Set、Map三个接口
- 它是不能改变的集合,不可再用add和put
- 不可以在调用时含有相同元素