18.01_集合框架(Map集合概述和特点)
- A:Map接口概述
- 查看API可以知道:
- 将键映射到值的对象
- 一个映射不能包含重复的键(键有唯一性)
- 每个键最多只能映射到一个值
- 查看API可以知道:
- B:Map接口和Collection接口的不同
- Map是双列的集合,Collection是单列的集合
- Map的键唯一,Collection的子体系Set是唯一的
- Map集合的数据结构值针对键有效,跟值无关(eg:HashMap中的键是有hashCode()算的);Collection集合的数据结构是针对元素有效
- HashMap和HashSet关系:HashSet底层依赖于HashMap
-
- PS:单列依赖于双列
- HashSet底层依赖于HashMap
TreeSet底层依赖于TreeMap
18.02_集合框架(Map集合的功能概述)
- A:Map集合的功能概述
- a:添加功能
- V put(K key,V value):添加元素。
- 如果键是第一次存储,就直接存储元素,返回null
- 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
- V put(K key,V value):添加元素。
- b:删除功能
- void clear():移除所有的键值对元素
- V remove(Object key):根据键删除键值对元素,并把值返回
-
//HashMap的键相当于HashSet具有唯一性。键是唯一的。值不唯一 HashMap<String, String> hm = new HashMap<>(); hm.put("张三", "北京"); hm.put("李四", "上海"); hm.put("王五", "广州"); hm.put("赵六", "北京"); System.out.println(hm);//HashMap的父类重写了toString()方法 String value = hm.remove("张三");//根据键删除,返回的是键对应的值 System.out.println(value); System.out.println(hm); ************************************** {李四=上海, 张三=北京, 王五=广州, 赵六=北京} 北京 {李四=上海, 王五=广州, 赵六=北京}
- c:判断功能
- boolean containsKey(Object key):判断集合是否包含指定的键
- boolean containsValue(Object value):判断集合是否包含指定的值
- boolean isEmpty():判断集合是否为空
-
HashMap<String, String> hm = new HashMap<>(); hm.put("张三", "北京"); hm.put("李四", "上海"); hm.put("王五", "广州"); hm.put("赵六", "北京"); boolean b1 = hm.containsKey("张三"); //判断是否包含指定的键 boolean b2 = hm.containsKey("xxx"); System.out.println(b1); System.out.println(b2); System.out.println("--------------------------"); boolean b3 = hm.containsValue("北京"); //判断是否包含指定的值 boolean b4 = hm.containsValue("深圳"); System.out.println(b3); System.out.println(b4); System.out.println("--------------------------"); boolean b5 = hm.isEmpty(); //判断集合是否为空 hm.clear();//:移除所有的键值对元素 boolean b6 = hm.isEmpty(); System.out.println(b5); System.out.println(b6); System.out.println(hm); ***************************************** true false -------------------------- true false -------------------------- false true {}
- d:获取功能
- Set<Map.Entry<K,V>> entrySet():获取键值对集合
- V get(Object key):根据键获取值
- Set keySet():获取集合中所有键的集合
- Collection values():获取集合中所有值的集合
- e:长度功能
- int size():返回集合中的键值对的个数
-
HashMap<String, String> hm = new HashMap<>(); hm.put("张三", "北京"); hm.put("李四", "上海"); hm.put("王五", "广州"); hm.put("赵六", "北京"); String value = hm.get("xx");//根据键获取值,如果没有指定的键返回null System.out.println(value); Collection<String> c = hm.values(); //获取所有值 System.out.println(c); System.out.println(hm.size()); //获取键值对的个数 ************************************** null [上海, 北京, 广州, 北京] 4
- a:添加功能
18.03_集合框架(Map集合的遍历之键找值)
- A:键找值思路:
- 获取所有键的集合(keySet()方法)
- 遍历键的集合,获取到每一个键
- 根据键找值
-
B:案例演示
-
Map集合的遍历之键找值
HashMap<String, Integer> hm = new HashMap<>(); hm.put("张三", 23); hm.put("李四", 24); hm.put("王五", 25); hm.put("赵六", 26); /*Set<String> keySet = hm.keySet(); //获取集合中所有的键 Iterator<String> it = keySet.iterator(); //获取迭代器 while(it.hasNext()) { //判断单列集合中是否有元素 String key = it.next(); //获取集合中的每一个元素,其实就是双列集合中的键 Integer value = hm.get(key); //根据键获取值 System.out.println(key + "=" + value); //打印键值对 }*/ for(String key : hm.keySet()) { //增强for循环迭代双列集合第一种方式 System.out.println(key + "=" + hm.get(key)); }
-
18.04_集合框架(Map集合的遍历之键值对对象找键和值)
- A:键值对对象找键和值思路:
- 获取所有键值对对象的集合(entrySet())
- 遍历键值对对象的集合,获取到每一个键值对对象
- 根据键值对对象找键和值
-
B:案例演示
-
Map集合的遍历之键值对对象找键和值
HashMap<String, Integer> hm = new HashMap<>(); hm.put("张三", 23); hm.put("李四", 24); hm.put("王五", 25); hm.put("赵六", 26); /*Set<Map.Entry<String, Integer>> entrySet = hm.entrySet(); //获取所有的键值对象的集合 Iterator<Entry<String, Integer>> it = entrySet.iterator();//获取迭代器 while(it.hasNext()) { Entry<String, Integer> en = it.next(); //获取键值对对象 String key = en.getKey(); //根据键值对对象获取键 Integer value = en.getValue(); //根据键值对对象获取值 System.out.println(key + "=" + value); }*/ /* * Entry<String,Integer> en键值对对象 * hm.entrySet():获取键值对集合 */ for(Entry<String,Integer> en : hm.entrySet()) { System.out.println(en.getKey() + "=" + en.getValue()); }/*调用HashMap内部类Entry的getKey(),getValue(); * Entry实现了Map.Entry接口。对Map.Entry的抽象方法(getKey(),getValue())进行了重写 */
-
-
Set<Map.entry<K,V>> entrySet()获取键值对集合,返回值是泛型为<Map.entry<K,V>>的Set集合
-
Map.entry<K,V>是一个对象(封装了键和值的对象)即:Map.entry<K,V> 键值对对象
-
Map.entry:entry是Map中的内部接口
18.05_集合框架(Map集合遍历的两种方式比较图解)
- A:画图演示
- Map集合遍历的两种方式比较
-
-
18.06_集合框架(HashMap集合键是Student值是String的案例)
- A:案例演示
- HashMap集合键是Person值是String的案例
-
@Override//Person类中要重写hashCode()和equals方法 public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HashMap<Person, String> hm = new HashMap<>(); hm.put(new Person("张三", 23), "北京"); hm.put(new Person("张三", 23), "北京"); hm.put(new Person("李四", 24), "上海"); System.out.println(hm); ******************************************************* {Person [name=张三, age=23]=北京, Person [name=李四, age=24]=上海}
- HashMap想保证键的唯一依赖于hashCode()和equals方法
- 自定义类型的键中,如果没有重写hashCode()和equals方法,当向HashMap添加元素时,调用的是Object类中的hashCode(),产生的哈希构造值都不一样 会导致HashMap集合中存在相同的键。
- 自定义类型的对象的类,自动生成hashCode()和equals方法。
18.07_集合框架(LinkedHashMap的概述和使用)
- A:案例演示
- LinkedHashMap的特点
- 底层是链表实现的可以保证怎么存就怎么取
-
HashMap<String, Integer> hm = new HashMap<>(); hm = new LinkedHashMap<>(); //LinkedHashMap保证怎么存就怎么取 hm.put("张三", 23); hm.put("李四", 24); hm.put("王五", 25); hm.put("赵六", 26); System.out.println(hm); ************************************ {张三=23, 李四=24, 王五=25, 赵六=26}
- LinkedHashMap的特点
18.08_集合框架(TreeMap集合键是Student值是String的案例)
- A:案例演示
- TreeMap集合:会对集合中的键进行排序
- TreeMap集合,键是Person值是String的案例
-
NO.1: @Override//Person类中要重写compareTo()用于集合中的键进行比较 public int compareTo(Person p) { int num = this.age - p.age; return num == 0 ? this.name.compareTo(p.name) : num; }
NO.2 TreeMap<Person, String> tm = new TreeMap<>(new Comparator<Person>() { //TreeMap传入比较器 @Override //创造比较器 public int compare(Person p1, Person p2) {//主要比较名字,次要比较年龄 int num = p1.getName().compareTo(p2.getName()); return num == 0 ? p1.getAge() - p2.getAge() : num; } }); tm.put(new Person("张三", 33), "北京"); tm.put(new Person("王五", 23), "广州"); tm.put(new Person("李四", 13), "上海"); tm.put(new Person("赵六", 43), "深圳"); System.out.println(tm); } ***************************************** {Person [name=张三, age=33]=北京, Person [name=李四, age=13]=上海, Person [name=王五, age=23]=广州, Person [name=赵六, age=43]=深圳}
18.09_集合框架(统计字符串中每个字符出现的次数)
-
A:案例演示
-
需求:统计字符串中每个字符出现的次数 String str = "aaaabbbcccccccccc"; char[] arr = str.toCharArray(); //将字符串转换成字符数组 HashMap<Character, Integer> hm = new HashMap<>(); //创建双列集合存储键和值
String str = "aaaabbbcccccccccc"; char[] arr = str.toCharArray(); //将字符串转换成字符数组 HashMap<Character, Integer> hm = new HashMap<>();//创建双列集合存储键和值 for(char c : arr) { //遍历字符数组 /*if(!hm.containsKey(c)) {//如果不包含这个键 hm.put(c, 1); //就将键和值为1添加 }else { //如果包含这个键 hm.put(c, hm.get(c) + 1);//就将键和值再加1添加进来 }*/ hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1); } for (Character key : hm.keySet()) { //遍历双列集合 System.out.println(key + "=" + hm.get(key)); } }**********************************************************************************************************a=4 b=3 c=10
-
18.12_集合框架(集合嵌套之HashMap嵌套HashMap)
- A:案例演示
- 集合嵌套之HashMap嵌套HashMap
-
HashMap<String, HashMap<Person, String>> hm = new HashMap<>(); //创建HashMap,键是String,值是HashMap HashMap<Person, String> jc0302 = new HashMap<>(); //创建HashMap集合对象,键是Person,值是String jc0302.put(new Person("张三", 23), "北京"); jc0302.put(new Person("李四", 24), "上海"); jc0302.put(new Person("马哥", 18), "辽宁"); HashMap<Person, String> jc0309 = new HashMap<>(); //创建HashMap集合对象,键是Person,值是String jc0309.put(new Person("王五", 25), "毛里求斯"); jc0309.put(new Person("赵六", 26), "铁岭"); hm.put("0302基础班", jc0302); hm.put("0309基础班", jc0309); for(String key : hm.keySet()) { //遍历嵌套的集合,String key代表hm中的每一个键 HashMap<Person, String> value = hm.get(key); //根据key获取的值是HashMap对象 for(Person k : value.keySet()) {//再遍历这个HashMap集合对象 System.out.print(key + "," +k + "," + value.get(k) + "\t"); } System.out.println(); } } ******************************************* 0309基础班,Person [name=赵六, age=26],铁岭 0309基础班,Person [name=王五, age=25],毛里求斯 0302基础班,Person [name=张三, age=23],北京 0302基础班,Person [name=李四, age=24],上海 0302基础班,Person [name=马哥, age=18],辽宁
18.13_集合框架(HashMap和Hashtable的区别)
- A:面试题
- HashMap和Hashtable的区别
- Hashtable是JDK1.0版本出现的,是线程安全的,效率低,HashMap是JDK1.2版本出现的,是线程不安全的,效率高
- Hashtable不可以存储null键和null值,HashMap可以存储null键和null值
- HashMap和Hashtable的区别
- B:案例演示
- HashMap和Hashtable的区别
-
/*Hashtable<String, String> ht = new Hashtable<>(); ht.put("abc", null); System.out.println(ht);*///会出现空指针异常,NullpointerException HashMap<String, String> hm = new HashMap<>(); hm.put("abc", null); System.out.println(hm);
18.14_集合框架(Collections工具类的概述和常见方法讲解)
- A:Collections类概述
- 针对集合操作 的工具类(集合工具类)
- Collection集合根接口
- B:Collections成员方法(静态)
-
ArrayList<String> list = new ArrayList<>(); list.add("c"); list.add("a"); list.add("b"); list.add("e"); list.add("d"); Collections.sort(list); //排序 System.out.println(list); int index = Collections.binarySearch(list, "c");//二分查找法(要保证集合有序) String max = Collections.max(list); //获取最大值 System.out.println(index); System.out.println(list); System.out.println(max); Collections.reverse(list); //将集合进行反转 Collections.shuffle(list);//对集合进行随机排序 System.out.println(list); **************************************** [a, b, c, d, e] 2 [a, b, c, d, e] e [a, e, b, c, d]
-
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)//随机排序
18.15_集合框架(模拟斗地主洗牌和发牌)
-
A:案例演示
-
模拟斗地主洗牌和发牌,牌没有排序
//买一副扑克 String[] num = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"}; String[] color = {"方片","梅花","红桃","黑桃"}; ArrayList<String> poker = new ArrayList<>(); //将数与花色进行拼接 for(String s1 : color) { for(String s2 : num) { poker.add(s1.concat(s2));//向集合中放牌。concat()连接俩字符串 } } poker.add("小王"); poker.add("大王");//以上将54张牌都放入集合中了 //洗牌 Collections.shuffle(poker);//Collections.shuffle()随机排序 //发牌 /* * 用三个集合(gaojin,longwu,me)模拟三个人 */ ArrayList<String> gaojin = new ArrayList<>(); ArrayList<String> longwu = new ArrayList<>(); ArrayList<String> me = new ArrayList<>(); ArrayList<String> dipai = new ArrayList<>(); for(int i = 0; i < poker.size(); i++) { if(i >= poker.size() - 3) { dipai.add(poker.get(i));//将集合中的最后三张给底牌集合 }else if(i % 3 == 0) { gaojin.add(poker.get(i)); }else if(i % 3 == 1) { longwu.add(poker.get(i)); }else { me.add(poker.get(i)); } } //看牌(即:每个集合中有哪些牌) System.out.println(gaojin); System.out.println(longwu); System.out.println(me); System.out.println(dipai);
-
18.16_集合框架(模拟斗地主洗牌和发牌并对牌进行排序的原理图解)
- A:画图演示
- 画图说明排序原理
-
18.17_集合框架(模拟斗地主洗牌和发牌并对牌进行排序的代码实现)
- A:案例演示
- 模拟斗地主洗牌和发牌并对牌进行排序的代码实现
-
//买一副牌 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中(最终HashMap:54个缩引对应54张牌) 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); } /* * TreeSet<Integer> ts中存取的是HashMap中的键,通过键来获取HashMap<Integer, String>中的值 */ 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();
18.18_集合框架(泛型固定下边界)
- ? super E
- *高级泛型
? extends E ?是任意子类,E是父类固定的(Person)
? super E E是子类 ?是父类 -
ArrayList<Person> list1 = new ArrayList<>(); list1.add(new Person("张三", 23)); list1.add(new Person("李四", 24)); ArrayList<Worker> list2 = new ArrayList<>(); list2.add(new Worker("王五", 25)); list1.addAll(list2);//? extends E ?是自乐E是父类固定的(Person) /* * Worker是Person的子类,所以存放Worker集合可以添加到存放Person的集合中 */ System.out.println(list1); ********************************************* [Person [name=张三, age=23], Person [name=李四, age=24], Person [name=王五, age=25]]
-
class CompareByAge implements Comparator<Person> {
@Override public int compare(Person p1, Person p2) {//比较器 int num = p1.getAge() - p2.getAge(); return num == 0 ? p1.getName().compareTo(p2.getName()) : num; } } TreeSet<Person> ts1 = new TreeSet<>(new CompareByAge()); ts1.add(new Person("张三", 23)); ts1.add(new Person("李四", 24)); TreeSet<Worker> ts2 = new TreeSet<>(new CompareByAge()); ts2.add(new Worker("王五", 25)); ts2.add(new Worker("赵六", 15)); ts2.add(new Worker("周七", 35));// ? super E 用父类的比较器 System.out.println(ts2); **************************************** [Person [name=赵六, age=15], Person [name=王五, age=25], Person [name=周七, age=35]]
18.19_day18总结
- 把今天的知识点总结一遍。