Java-Map 红太狼 2024-03-26 13:46 17阅读 0赞 ## 一、比较器排序 ## > TreeSet是会对元素进行**排序去重**,有两种实现方案 > 1、 使用空参构造方法创建出的TreeSet,底层使用**自然排序**,即元素要实现Comparable接口才能实现排序 > 2、 可以使用有参构造,在创建TreeSet集合时,传入一个**Comparator 比较器**,这样存入的元素就会按照该比较器指定的排序方案排序( 不再使用默认的自然排序) > TreeSet(Comparator comparator) 构造一个新的空 TreeSet,它根据指定比较器进行排序。 > 使用步骤 > 自定义类实现Comparator 接口 > 重写compar(T o1,T o2)方法 > o1 就是之前compareTo方法中的this,即正在存储的元素 > o2 就是之前compareTo方法中的o,即以前存储过的元素 > 方法返回值与之前compareTo方法的返回值一样 > 返回0 去重 > 返回负数放左边 > 返回正数放右边 > 在创建TreeSet时,创建该比较器对象,传入TreeSet的构造方法 ## 二、Collections ## > 类似于与Arrays,Collections是集合的工具类,方法都是静态的 > Collections.reverse(List<?> list) 反转 > Collections.shuffle(List<?> list) 混洗 > Collections.sort(List<?> list) 排序 ArrayList<Integer> list = new ArrayList<>(); list.add(3); list.add(2); list.add(5); list.add(4); list.add(2); list.add(1); System.out.println(list); // 排序 只能是升序 Collections.sort(list); System.out.println(list); // 反转 Collections.reverse(list); System.out.println(list); // 混洗 Collections.shuffle(list); System.out.println(list); 结果: [3, 2, 5, 4, 2, 1] [1, 2, 2, 3, 4, 5] [5, 4, 3, 2, 2, 1] [2, 1, 2, 5, 3, 4] ## 三、Map<K,V> ## > Map代表**双列集合**,一次存储一对键值对(K,V) > Map是接口,代表是键映射到值的对象,一个Map**不能包含重复的键**,**值允许重复**.每个键最多只能映射到一个值,即可以通过键找到值,但是不能通过值找键. > 方法都是非常常见的方法,但是Map是接口无法演示 > Map有两个常用实现类 > HashMap > TreeMap ## 四、HashMap\[重点\] ## > HashMap是Map的实现类,现在JDK8及以后底层是由数组+链表+红黑树实现并允许使用 null 值和 null 键 > HashMap存储的元素是不保证迭代顺序,存储的键不允许重复,值允许重复 > > 除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同 > (HashMap允许使用null值和null键,Hashtable不允许) > > 补充: **Hashtable**是**线程安全**的map集合,效率低 ; HashMap是**线程不安全**的,效率高**ConcurrentHashMap 即安全又高效的Map集合** > HashMap的容量和扩容: 初始容量16,加载因子0.75 阈值是 16 \* 0.75,达到阈值扩容至原来的2倍ps: 昨天学习的HashSet所有特性,其实就是HashMap的特性,包括去重原理 ### **4.1 方法演示** ### > **构造方法** > HashMap() 构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。 > HashMap(int initialCapacity) 构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。 > HashMap(int initialCapacity, float loadFactor) 构造一个带指定初始容量和加载因子的空 HashMap。 > HashMap(Map<? extends K,? extends V> m) 构造一个映射关系与指定 Map 相同的新 HashMap。 > **方法** > 每个都很重要!!!! // 创建空的HashMap; HashMap<String,Integer> map = new HashMap<>(); System.out.println(map ); // 添加元素,一次添加一对,键值 // put方法的返回值,如果该键之前没有映射值,返回null // 如果该键之前映射的有值,则将值覆盖,返回上次的旧值 Integer v1 = map.put("a",1); System.out.println(v1 ); Integer v2 = map.put("a", 2); System.out.println(v2 ); Integer v3 = map.put("d", 4); System.out.println(v3 ); map.put("b",2); System.out.println(map ); // 取出元素 // 通过键返回值 Integer v = map.get("a"); System.out.println(v ); // 集合大小(元素个数) System.out.println(map.size() ); // 集合是否为空 System.out.println(map.isEmpty() ); // 清空集合 //map.clear(); // 集合大小(元素个数) //System.out.println(map.size() ); // 集合是否为空 //System.out.println(map.isEmpty() ); // 移除元素,根据键移除整个键值对,返回值 Integer a = map.remove("a"); System.out.println(a ); System.out.println(map ); /** * boolean containsKey(Object key) * 判断集合中是否包含指定键,有则返回 true。 * boolean containsValue(Object value) * 判断集合中是否包含指定值,有则返回 true。 */ System.out.println(map.containsKey("A")); System.out.println(map.containsValue(11)); ### **4.2 迭代/遍历** ### > Map 接口提供**三种*collection 视图***,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容 > 1 、 Set<Key> **keySet()** 键集,返回一个Set集合,其中只有键 > 2、 Collection<Value> **values()** 值集,返回一个Collection集合,其中只有值 > 3、 Set<Map.Entry<K,V>> **entrySet()** 键值映射集,返回一个Set集合,其中放着key-value对象 #### **4.2.1 键集** #### HashMap<String, Integer> map = new HashMap<>(); map.put("a", 1); map.put("b", 2); map.put("c", 3); map.put("d", 4); System.out.println(map); // 键集遍历 Set<String> keySet = map.keySet(); // 获得迭代器 Iterator<String> iterator = keySet.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } System.out.println("---------"); for (String key : keySet) { System.out.println(key); } #### **4.2.2 值集** #### // 值集 Collection<Integer> value = map.values(); Iterator<Integer> iterator = value.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } System.out.println("---------"); for (Integer integer : value) { System.out.println(integer); } #### **4.2.3 键值映射集 \[非常重要\]** #### > Entry是Map接口中的内部接口,代表是一个键值对,即包含键和值.且该Entry接口中提供了关于操作单个键,值的方法 > **K getKey()** > **V getValue()** // 键值映射集 Set<Map.Entry<String,Integer>> entrySet = map.entrySet(); Iterator<Map.Entry<String,Integer>> iterator = entrySet.iterator(); while (iterator.hasNext()) { Map.Entry<String,Integer> entry = iterator.next(); String key = entry.getKey(); Integer value = entry.getValue(); System.out.println(key + "-->" + value); } System.out.println("----====="); for (Map.Entry<String, Integer> entry : entrySet) { System.out.println(entry); System.out.println(entry.getKey()); System.out.println(entry.getValue()); } ### **4.3 去重原理** ### > HashMap的去重其实就是HashSet的去重,因为HashSet底层就是HashMap > 1、在创建HashSet时,其实在底层创建了HashMap ![13ea536f4c8829570ded2aed02fd0258.png][] 2、在向set中添加元素时,其实是向map的key上添加 ![018b07726e2d1e790b998acfe725faad.png][] > 所以HashMap的键的去重原理就是 > 向键存储数据时,**先调用键的hashcode()方法** > 如果hashcode值不一样则直接存储 > 如果hashcode值一样,**再调用元素的equals()方法** > 如果equals方法返回false,则存储 > 如果equals方法返回true,则不存储 ### **4.4 HashMap的应用** ### > 场景一: 适合有关联映射的场景 设计方法,传入字符串,输出该字符串中每个字符出现的次数,使用HashMap实现例如: “abcHelloabcWorld”,输出 a出现2次,b出现2次,,,l出现3次,H出现1次 HashMap<String, Integer> map = new HashMap<>(); Scanner scanner = new Scanner(System.in); String str = scanner.next(); // char[] chars = str.toCharArray(); 也可转为字符数组 String[] strArr = str.split(""); for (int i = 0; i < strArr.length; i++) { String s =strArr[i]; if(!map.containsKey(s)){ map.put(strArr[i], 1); }else { Integer count = map.get(s); map.put(strArr[i],++count); } } System.out.println(map); Set<Map.Entry<String,Integer>> set = map.entrySet(); Iterator<Map.Entry<String,Integer>> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } > 场景二: Map可以当实体类对象 public class Student{ private int age; private String name; // ... } Student s1 = new Student(18,"zs"); s1.getAge(); s1.getName(); 使用Map模拟对象 HashMap<String, Object> stu = new HashMap<>( ); stu.put("age",18); stu.put("name","zs"); stu.put("sex","男"); ## 五、TreeMap ## > TreeMap底层是红黑树(平衡二叉树的一种)同样式存储键值对,键不允许重复且还会排序默认是根据键元素的自然顺序排序或者,根据创建TreeMap时指定的**Comparator比较器来排序** ### **5.1 方法演示** ### TreeMap<String, Integer> map = new TreeMap<>( ); map.put("b",2); map.put("e",5); map.put("a",1); map.put("a",2); map.put("d",4); map.put("c",3); // 其他正常的map方法... // 三个遍历方法... // 特殊的,有关于头尾操作的方法 // 获得排序后的第一个 String key = map.firstKey( ); // 获得排序后的第一个Entry Map.Entry<String, Integer> entry = map.firstEntry( ); System.out.println(entry ); ### **5.2 TreeMap排序去重原理** ### > 昨天学习的TreeSet的底层其实就是TreeMap * 创建TreeSet时,创建TreeMap ![3b3d114f911c6363efe9c952e547d713.png][] * 向set集合添加元素时,其实是向TreeMap的键添加元素 ![b0c8388aafd6a99c50d8c7ba025a4665.png][] > 即TreeMap的排序去重原理是什么?其实如果**自然排序就是compareTo()**,如果是**比较器排序就是compar()方法** > 方法返回0 去重 > 方法返回负数 放在树左侧 > 方法返回正数 放在树的右侧 ## 六、总结 ## > 集合体系中最重要最常见的两个集合是ArrayList,HashMap > 其他的, > 记住常用的API(crud和遍历) > 记住List和Set区别 > 记住ArrayList和LinkedList区别 > 记住HashMap扩容,去重原理 > 记住TreeMap的排序去重原理 [13ea536f4c8829570ded2aed02fd0258.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/26/b2d9272f7f69468cb4206fd2c73c4ab1.png [018b07726e2d1e790b998acfe725faad.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/26/9d9e0787a22a495aa93130490d8845f0.png [3b3d114f911c6363efe9c952e547d713.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/26/ca4d487a37af44cfa84920fa641ed76d.png [b0c8388aafd6a99c50d8c7ba025a4665.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/26/c251d81db1c04277972daec0ce8ea8a8.png
相关 Java开发面经分享:javamap遍历方式 2. ZooKeeper 介绍 2.1. ZooKeeper 由来 正式介绍 ZooKeeper 之前,我们先来看看 ZooKeeper 的由来,还挺有意思的。 约定不等于承诺〃/ 2022年08月31日 06:36/ 0 赞/ 293 阅读
相关 Java开发热门前沿知识!javamap赋值 引言 众所周知,软件系统有三高:\\高并发、高性能、高可用。\\三者既有区别也有联系,门门道道很多,全面讨论可以大战三天三夜。 高并发对于Java开发者来说都不陌生,每 £神魔★判官ぃ/ 2021年07月20日 11:39/ 0 赞/ 598 阅读
还没有评论,来说两句吧...