Map
今天的主要内容
Map接口概述
-
Map集合的两种遍历方式
通过键找值keySet
-
通过键值对对象获取键和值
- 涉及到Map.Entry的认识
-
HashMap
- 自定义对象必须重写equals和hashCode方法
LinkedHashMap
-
TreeMap
- 统计字符串中每个字符出现的次数
-
HashMap和Hashtable的区别
线程安全方面
存储键值对的数据类型方面
一、集合框架(Map集合概述和特点)
-
Map接口概述
-
查看API可以知道:
将键映射到值的对象( maps keys to values)
一个映射不能包含重复的键(A map cannot contain duplicate keys)
每个键最多只能映射到一个值( each key can map to at most one value.)
-
-
Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
二、集合框架(Map集合的功能概述)
-
A:Map集合的功能概述
-
a:添加功能
-
V put(K key,V value):添加元素。
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
相同的键不存储,值覆盖
-
-
b:删除功能
void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回
-
c:判断功能
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
-
d:获取功能
Set<Map.Entry<K,V>> entrySet():
V get(Object key):根据键获取值
Set<K> keySet():获取集合中所有键的集合
Collection<V> values():获取集合中所有值的集合
-
e:长度功能
- int size():返回集合中的键值对的个数
-
-
测试程序
public class TestMap { public static void main(String[] args) { Map<String,Integer> map = new HashMap<>(); //添加功能 System.out.println("====V put(K key,V value):添加元素.===="); testPut(map); //删除功能 System.out.println("====V remove(Object key):===="); testRemove(map); //判断功能 System.out.println("==============判断功能=============="); testBoolean(map); System.out.println(" ==========e:长度功能 int size()=========="); testSize(map); } public static void testPut(Map<String,Integer> map) { /* a:添加功能 V put(K key,V value):添加元素。 * 如果键是第一次存储,就直接存储元素,返回null * 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值 */ Integer i1 = map.put("小王", 21); Integer i2 = map.put("小李", 22); Integer i3 = map.put("小王", 23); Integer i4 = map.put("小花", 24); Integer i5 = map.put("小明", 25); System.out.println(map); System.out.println(i1); System.out.println(i2); System.out.println(i3); System.out.println(i4); System.out.println(i5); /* * 在JDK1.8中输出结果为: * ------------------------------- * ====V put(K key,V value):添加元素.==== {小李=22, 小明=25, 小王=23, 小花=24} null //返回null表示值没有被覆盖 null 21 //键相等,值覆盖,返回被覆盖的值 null null * ------------------------------- * */ } public static void testRemove(Map<String,Integer> map) { /* * b:删除功能 * void clear():移除所有的键值对元素 * V remove(Object key):根据键删除键值对元素,并把值返回 */ Integer i1 = map.remove("小王"); Integer i2 = map.remove("小李"); System.out.println(i1); System.out.println(i2); System.out.println("删除后,集合中元素有:"); System.out.println(map); /* * 在JDK1.8中输出结果为: * --------------------------------- * ====V remove(Object key):==== 23 22 删除后,集合中元素有: {小明=25, 小花=24} --------------------------------- * */ } public static void testBoolean(Map<String,Integer> map) { /* * c:判断功能 * * boolean containsKey(Object key):判断集合是否包含指定的键 * boolean containsValue(Object value):判断集合是否包含指定的值 * boolean isEmpty():判断集合是否为空 */ System.out.println("Map集合是否为空?" + map.isEmpty()); System.out.println("Map集合是否包含指定的键“小花? " + map.containsKey("小花")); System.out.println("Map集合是否包含指定的值:28 " + map.containsValue(28)); /* * 在JDK1.8中输出结果为: * --------------------------------------- * ==============判断功能============== Map集合是否为空?false Map集合是否包含指定的键“小花? true Map集合是否包含指定的值:28 false --------------------------------------- * */ } public static void testSize(Map<String,Integer> map) { System.out.println("Map中键值对个数为: " + map.size()); /* * 在JDK1.8中输出结果为: * --------------------------------------- * ==========e:长度功能 int size()========== Map中键值对个数为: 2 --------------------------------------- * */ } }
三、集合框架(Map集合的遍历之键找值)
-
键找值思路:
-
获取所有键的集合
- Set<K> keySet()——返回所有键的集合
-
遍历键的集合,获取到每一个键
- Set集合中的iterator方法
-
根据键找值
- V get(Object key)
-
-
程序——Map集合的遍历之键找值
public static void main(String[] args) { Map<String,Integer> map = new HashMap<>(); map.put("小王", 21); map.put("小李", 22); map.put("小花", 24); map.put("小明", 25); //获取所有键 Set<String> set = map.keySet(); //获取迭代器 Iterator<String> i = set.iterator(); //遍历输出所有键 while(i.hasNext()) { String key = i.next(); System.out.println("key = " + key + " value = " + map.get(key)); } //增强的for循坏输出键值对 /* for(String key : map.keySet()) { System.out.println("key = " + key + " value = " + map.get(key)); }*/ }
四、集合框架(Map集合的遍历之键值对对象找键和值)
-
键值对对象找键和值思路:、
-
获取所有键值对对象的集合——entrySet方法返回Map.Entry类型
- 将所有的Map.Entry对象放在Set集合中
-
* 遍历键值对对象的集合,获取到每一个键值对对象
* Set接口中的iterator方法遍历出每一个Map.Entry对象
* 根据键值对对象找键和值
* 利用Map.Entry接口中的getKey()和getValue方法获取键和值
- 案例演示
-
Map集合的遍历之键值对对象找键和值
public class TestIterator_3 { public static void main(String[] args) { Map<String,Integer> map = new HashMap<>(); map.put("小王", 21); map.put("小李", 22); map.put("小花", 24); map.put("小明", 25); /*//Map.Entry说明Entry是Map的内部接口 //将键和值封装成Entry对象,并存储在Set集合中 Set<Map.Entry<String,Integer>> entrySet = map.entrySet(); //获取每一个对象 Iterator<Map.Entry<String, Integer>> i = entrySet.iterator(); while(i.hasNext()) { Map.Entry<String,Integer> me = i.next(); System.out.println("key = " + me.getKey() + "value = " + me.getValue()); }*/ for(Map.Entry<String, Integer> e : map.entrySet()) { System.out.println("key = " + e.getKey() + "value = " + e.getValue()); } } } /* * 在JDK1.8中输出结果为: * ----------------------- * key = 小李value = 22 key = 小明value = 25 key = 小王value = 21 key = 小花value = 24 ------------------------ * */
-
五、HashMap
-
类似于HashSet对键唯一的要求
- 在自定义类型的时候,一定要重写HashCode和equals方法
六、LinkedHashMap
- 链表实现:可保证怎么存就怎么取
七、TreeMap
-
自定义对象必须实现Comparable接口或者Comparator接口
自定义对象若实现Comparable接口,则必须重写compareTo方法
自定义对象若实现Comparator接口,则必须重写compare方法
八、集合框架(统计字符串中每个字符出现的次数)
需求:统计字符串中每个字符出现的次数
-
分析
- 从键盘获取字符串输入,将字符串转换为字符数组
- 创建HashMap集合,将字符串中的字符作为key存入到HashMap中
- 当该字符包含在HashMap中时,则增加value
- 遍历HashMap输出字符串中每一个字符出现的次数
-
程序
public class TestMap_2 { public static void main(String[] args) { //1. 从键盘获取字符串输入,将字符串转换为字符数组 Scanner input = new Scanner(System.in); System.out.println("请输入要统计的字符串"); String string = input.nextLine(); char[] charArr = string.toCharArray(); //2. 创建HashMap集合,将字符串中的字符作为key存入到HashMap中 HashMap<Character, Integer> hashMap = new HashMap<>(); //3. 当该字符包含在HashMap中时,则增加value for(char c : charArr) { /* if(hashMap.containsKey(c)) { //增加value hashMap.put(c,hashMap.get(c) + 1); } else { hashMap.put(c,1); } */ //上段代码也等价于 hashMap.put(c, hashMap.containsKey(c) ? hashMap.get(c) + 1 : 1); } //4. 遍历HashMap输出字符串中每一个字符出现的次数 //在这儿我们使用通过键值对象获取键和值 Set<Map.Entry<Character, Integer>> set = hashMap.entrySet(); //获取set的迭代器 Iterator<Map.Entry<Character, Integer>> iterator = set.iterator(); //遍历输出键和值 while(iterator.hasNext()) { //获取Entry对象 Entry<Character, Integer> entry = iterator.next(); System.out.println(entry.getKey() + "出现的次数为:" + entry.getValue()); } } } /* * 在JDK1.8中输出结果为: * ---------------- * 请输入要统计的字符串 aaaabbbbbcc a出现的次数为:4 b出现的次数为:5 c出现的次数为:2 ---------------- * */
九、集合框架(HashMap和Hashtable的区别)
-
A:面试题
-
HashMap和Hashtable相同点
- 底层实现都是哈希算法,都是双列集合
-
HashMap和Hashtable的区别
Hashtable是JDK1.0版本出现的,是线程安全的,效率低,HashMap是JDK1.2版本出现的,是线程不安全的,效率高
Hashtable不可以存储null键和null值,HashMap可以存储null键和null值
-
十、集合框架(Collections工具类的概述和常见方法讲解)
-
A:Collections类概述
- 针对集合操作 的工具类
-
B:Collections成员方法
public static <T> void sort(List<T> list) public static <T> int binarySearch(List<?> list,T key) public static <T> T max(Collection<?> coll) public static void reverse(List<?> list) public static void shuffle(List<?> list)
十一、集合框架(模拟斗地主洗牌和发牌)
模拟斗地主洗牌和发牌
-
程序
//买一副牌 String[] num = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"}; String[] color = {"方片","梅花","红桃","黑桃"}; HashMap<Integer, String> hm = new HashMap<>(); //存储索引和扑克牌 ArrayList<Integer> list = new ArrayList<>(); //存储索引 int index = 0; //索引的开始值 for(String s1 : num) { for(String s2 : color) { hm.put(index, s2.concat(s1)); //将索引和扑克牌添加到HashMap中 list.add(index); //将索引添加到ArrayList集合中 index++; } } hm.put(index, "小王"); list.add(index); index++; hm.put(index, "大王"); list.add(index); //洗牌 Collections.shuffle(list); //发牌 TreeSet<Integer> gaojin = new TreeSet<>(); TreeSet<Integer> longwu = new TreeSet<>(); TreeSet<Integer> me = new TreeSet<>(); TreeSet<Integer> dipai = new TreeSet<>(); for(int i = 0; i < list.size(); i++) { if(i >= list.size() - 3) { dipai.add(list.get(i)); //将list集合中的索引添加到TreeSet集合中会自动排序 }else if(i % 3 == 0) { gaojin.add(list.get(i)); }else if(i % 3 == 1) { longwu.add(list.get(i)); }else { me.add(list.get(i)); } } //看牌 lookPoker("高进", gaojin, hm); lookPoker("龙五", longwu, hm); lookPoker("冯佳", me, hm); lookPoker("底牌", dipai, hm);
}
public static void lookPoker(String name,TreeSet<Integer> ts,HashMap<Integer, String> hm) {
System.out.print(name + "的牌是:");
for (Integer index : ts) {
System.out.print(hm.get(index) + " ");
}
System.out.println();
}