【JAVA数据结构】哈希表-HashSet and HashMap(二)

简介: JAVA数据结构 & 哈希表 -HashSet and HashMap

5. 集合类的基本用途与使用

5.1 实例化Map

一般用普通类实例化接口的形式,这样这个引用的功能更加具有针对性。


接下来来看看Map的一些基本功能(高亮即重点)


方法 解释

V get(Object key) 返回key对应的value值

V getOrDefault(Object key, V defaultValue) 返回对应value,不存在则返回defaultValue

V put(K key, V value) 放置键值对(key重复则覆盖)

V remove(Object key) 根据唯一的key删除键值对

Set keySet() key不重复,将所有key值放在Set里并返回

Collection values() 将所有values放在集合中并返回

Set<Map.Entry<K, V>> entrySet() 返回所有键值对集(entry即条目)

boolean containsKey(Object key) 是否存在key值

boolean containsValue(Object value) 是否存在value值

其中还有一个特别重要的静态内部接口,Entry


这里我们可以理解为,将key和value打包起来了,成为一个独立的引用,其实里面


方法 解释

K getKey()  获取键值对的key值
V getValue()  获取键值对的value值
V setValue(V value) 设置键值对的value值
Set<Map.Entry<Integer, Integer>> set = hashMap.entrySet();
Map.Entry<Integer, Integer>[] entry = (Map.Entry<Integer, Integer>[]) set.toArray();//把map的 key 和 value 组装成一个整体
entry[0].getKey();
entry[0].getValue();
entry[0].setValue();


无法设置key,转化为Set有什么用,等一下将Set的时候细说!


接下来解答一些疑惑,就是为什么返回类型是接口/抽象类型,但是仍然可以正常使用?


原因就是,重写方法的规矩除了完全相等以外,还有一个例外

就是,返回类型呈现继承/实现关系,【父亲方法的返回类型】被【子类方法的返回类型】继承或者实现,也是重写!

这样,返回类型就可以是普通类啦,并且哈希实现就是哈希,树实现就是树。

至于Entry的本质



这是源码,Entry被Node实现后,


只要被Node实例化,【对应的引用就有了对应的Node】,也就有了对应的【key,value】

这是因为,方法被重写后,访问key和value并非private

这样就能够在父类访问子类成员了!

这样,使用Entry的get…方法,就相当于有对应的Node引用使用了get…方法,就获取到了对应的key,value值

对于entrySet()方法



看不懂不重要,重要的是解决了我们的疑问


就是,Entry被一个特定的Node实例化后,Node被删除,还访问得到吗?

明确的告诉你,还可以,因为这里的节点被(深)拷贝了一份,Entry是被这份拷贝实例化的!

注意

key唯一,value不唯一,key不可被设置,只能删掉重新放置

哈希里是可以存放null的,而树不可以(因为null不能比较,会抛异常的)

Map并不是”Collection家族“的

5.2 实例化Set

下面是Set的基本功能(高亮即重点)


方法 解释

boolean add(E e) 增加元素,重复则会失败,返回false

void clear() 清空集合

boolean contains(Object o) 查看元素是否存在

Iterator iterator() 返回迭代器

boolean remove(Object o) 删除对应元素

int size() 返回集合大小

boolean isEmpty() 集合是否为空

Object[] toArray() 转化为数组(非基本数据类型数组!)

boolean containsAll(Collection<?> c) 查询c集合的所有元素是否个个都存在

boolean addAll(Collection<? extends E> c) 添加一整个集合的所有元素,去重作用(完全不重复则返回true)(有现成的集合类的时候适用)

5.2.1 迭代器

这个“工具”的作用就是遍历集合


用法如下:

hasNext() 与 next() 这两个方法打配合
public static void main(String[] args) {
    Map<String, Integer> hashMap = new HashMap<>();
    hashMap.put("小卡拉", 3);
    hashMap.put("马拉圈", 4);
    hashMap.put("芜湖", 5);
    System.out.println(hashMap.get("小"));
    Set<Map.Entry<String, Integer>> set = hashMap.entrySet();
    //for-each 语法遍历
    for(Map.Entry<String, Integer> s : set) {
        System.out.print(s.getKey() + " " + s.getValue() + " ");
    }
    //迭代器遍历法
    Iterator<Map.Entry<String, Integer>> iter =  set.iterator();
    //Iterator<?> 用通配符也可以
    while(iter.hasNext()) {
        System.out.print(iter.next() +  " ");
    }
}


5.2.2 toArray()

这个方法有两个用法

(T[])set.toArray();
//需要强制类型转化!由于擦除机制,数组的返回是Object[]
set.toArray(arr);
//这个arr必须是对应的非基本数据类型数组!或者父类数组
//set里面的元素被整合到arr里了
//返回值可以不接收,接收的话,方式跟上面一样


需要重点强调的一点是,基本数据类型的数组与其包装类的数组不能直接相互转化(自然也不存在自动拆箱装箱),必须遍历一遍!!!


其他方法相对简单,不细说


注意

Set是Collection家族的接口类

key值唯一,Set重点在于除重

key要修改,必须删除再添加

树的key不能是null,因为需要比较

TreeSet/HashSet底层由Map实现,value为Object类型的一个默认对象,key就是key

节省功夫嘛


Set和Map 还可用 LinkedHashSet和LinkedHashMap实例化

这维护了双向链表,可以记录元素的插入次序

6. 哈希部分源码

刚才已经接触了一些源码了,接下来只有一些补充了

6.1 HashMap

6.1.1 一些常量




这个是默认的表的默认容量


这个是表的最大容量


这个是负载因子默认最大值


这个哈希桶树化临界值

即桶内节点达到8,就会折叠成红黑树(原本只是链表)


这个是哈希桶退化为链表的临界值

即桶内节点被删除到6,就会退化成链表(原本是红黑树)


这个是哈希桶树化前提的前提

就是,表的容量很少时,可能会导致桶内的东西太多了【就是冲突次数多】

那么规定一个值,当表的已有元素总数(节点总个数)达到这个值的时候,才考虑折叠链表为红黑树,其他情况直接扩容即可【其他情况是指,桶内元素达到界值后不选择树化,而是扩容哈希表】

为了避免进行扩容、树形化选择的冲突,这个值不能小于 4 * TREEIFY_THRESHOLD

树化方法treeifyBin 就不带大家看了


6.1.2 哈希方法


此方法的作用是让值放的更分散

6.1.3 调整容量

这个操作是将容量调整为最接近的二进制数(较大)


即2, 4, 8, 16…

原理就是,让二进制序列最左边的1之后的位都变成1,

【10101】= =》【11111】= =》【100000】

右移按位与是让这个位【1】成倍数往后扩展

就是原本可能只有一个1扩展为两个1,扩展到四个1,这样最快

在一个构造方法中有用到


用途:搭配哈希方法降低冲突率

6.1.4 构造方法


提供容量和负载因子

提供容量

什么都不提供

提供一个Map,将整个Map的所有元素(拷贝成新的一个引用)

6.1.5 LinkedHashMap

在HashMap中并没有实例化对象LinkedHashMap的构造方法,但是有继承它的…

了解即可

6.2 HashSet

底层也是Map,key就是key,value是一个Object默认值

主要带大家看看构造方法

不带参数构造方法

提供一个集合引用,将所有元素导入Set里

提供容量和负载因子

提供容量

提供容量,负载因子以及布尔类型

这个类型并没有什么用,只是区分其他构造方法而已



就是构造LinkedHashMap( )


本质上LinkedHashSet就是用到的就是这个方法



文章到此结束!谢谢观看

可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆!


这是我的代码仓库!(在马拉圈的23.2里)代码仓库


Map&Set · 代码位置


邮箱:2040484356@qq.com


相关文章
|
4天前
|
存储 安全 算法
【JAVA】HashMap扩容性能影响及优化策略
【JAVA】HashMap扩容性能影响及优化策略
|
4天前
|
存储 Java 索引
【JAVA】HashMap的put()方法执行流程
【JAVA】HashMap的put()方法执行流程
|
5天前
|
存储 安全 Java
Java程序员必须掌握的数据结构:HashMap
HashMap底层原理实现是每个Java Boy必须掌握的基本技能,HashMap也是业务开发每天都需要遇到的好伙伴。如此基础且核心的底层数据结构,JDK也给其赋予了线程安全的功能,我们来看看~
21 1
Java程序员必须掌握的数据结构:HashMap
|
6天前
|
存储 安全 Java
Java并发编程中的高效数据结构:ConcurrentHashMap解析
【4月更文挑战第25天】在多线程环境下,高效的数据访问和管理是至关重要的。Java提供了多种并发集合来处理这种情境,其中ConcurrentHashMap是最广泛使用的一个。本文将深入分析ConcurrentHashMap的内部工作原理、性能特点以及它如何在保证线程安全的同时提供高并发性,最后将展示其在实际开发中的应用示例。
|
7天前
|
存储 安全 Java
Java集合篇之set,面试官:请说一说HashSet、LinkedHashSet、TreeSet的区别?
Java集合篇之set,面试官:请说一说HashSet、LinkedHashSet、TreeSet的区别?
12 0
|
11天前
|
存储 供应链 Java
《Java 简易速速上手小册》第3章:Java 数据结构(2024 最新版)
《Java 简易速速上手小册》第3章:Java 数据结构(2024 最新版)
8 1
|
15天前
|
存储 算法 安全
上机实验四 哈希表设计 西安石油大学数据结构
上机实验四 哈希表设计 西安石油大学数据结构
16 0
|
18天前
|
Java API
编码的奇迹:Java 21引入有序集合,数据结构再进化
编码的奇迹:Java 21引入有序集合,数据结构再进化
16 0
|
23天前
|
消息中间件 存储 搜索推荐
深入理解栈和队列(二):队列
深入理解栈和队列(二):队列
36 0
|
2月前
|
存储 开发工具
栈存储结构详解
栈存储结构详解
42 7