【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


目录
相关文章
|
存储 算法 安全
探究‘公司禁用 U 盘’背后的哈希表算法与 Java 实现
在数字化办公时代,信息安全至关重要。许多公司采取“禁用U盘”策略,利用哈希表算法高效管理外接设备的接入权限。哈希表通过哈希函数将设备标识映射到数组索引,快速判断U盘是否授权。例如,公司预先将允许的U盘标识存入哈希表,新设备接入时迅速验证,未授权则禁止传输并报警。这有效防止恶意软件和数据泄露,保障企业信息安全。 代码示例展示了如何用Java实现简单的哈希表,模拟公司U盘管控场景。哈希表不仅用于设备管理,还在文件索引、用户权限等多方面助力信息安全防线的构建,为企业数字化进程保驾护航。
Java之HashMap详解
本文介绍了Java中HashMap的源码实现(基于JDK 1.8)。HashMap是基于哈希表的Map接口实现,允许空值和空键,不同步且线程不安全。文章详细解析了HashMap的数据结构、主要方法(如初始化、put、get、resize等)的实现,以及树化和反树化的机制。此外,还对比了JDK 7和JDK 8中HashMap的主要差异,并提供了使用HashMap时的一些注意事项。
448 2
Java之HashMap详解
|
存储 安全 Java
Java 集合框架中的老炮与新秀:HashTable 和 HashMap 谁更胜一筹?
嗨,大家好,我是技术伙伴小米。今天通过讲故事的方式,详细介绍 Java 中 HashMap 和 HashTable 的区别。从版本、线程安全、null 值支持、性能及迭代器行为等方面对比,帮助你轻松应对面试中的经典问题。HashMap 更高效灵活,适合单线程或需手动处理线程安全的场景;HashTable 较古老,线程安全但性能不佳。现代项目推荐使用 ConcurrentHashMap。关注我的公众号“软件求生”,获取更多技术干货!
270 3
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
180 1
|
9月前
|
存储 安全 Java
Java 集合面试题从数据结构到 HashMap 源码剖析详解及长尾考点梳理
本文深入解析Java集合框架,涵盖基础概念、常见集合类型及HashMap的底层数据结构与源码实现。从Collection、Map到Iterator接口,逐一剖析其特性与应用场景。重点解读HashMap在JDK1.7与1.8中的数据结构演变,包括数组+链表+红黑树优化,以及put方法和扩容机制的实现细节。结合订单管理与用户权限管理等实际案例,展示集合框架的应用价值,助你全面掌握相关知识,轻松应对面试与开发需求。
447 3
|
存储 缓存 安全
Java HashMap详解及实现原理
Java HashMap是Java集合框架中常用的Map接口实现,基于哈希表结构,允许null键和值,提供高效的存取操作。它通过哈希函数将键映射到数组索引,并使用链表或红黑树解决哈希冲突。HashMap非线程安全,多线程环境下需注意并发问题,常用解决方案包括ConcurrentHashMap和Collections.synchronizedMap()。此外,合理设置初始化容量和加载因子、重写hashCode()和equals()方法有助于提高性能和避免哈希冲突。
803 17
Java HashMap详解及实现原理
|
存储 NoSQL Java
【数据结构进阶】哈希表
哈希表是一种高效的数据结构,通过哈希函数实现数据映射,支持平均O(1)时间复杂度的查找、插入和删除操作。本文详细介绍了哈希表的基本概念、哈希函数的设计(如直接定址法和除留余数法)以及哈希冲突的解决方法(如开放定址法和链地址法)。同时,文章通过代码实例展示了线性探测和链地址法两种哈希表的实现过程,并分析了各自的优缺点。最后总结指出,合理选择哈希函数和冲突解决策略是优化哈希表性能的关键。
1257 2
|
存储 安全 Java
如何优雅地回答HashSet与HashMap的区别?看这里!
哈喽,大家好!我是小米,29岁程序员。本文聚焦Java开发中经典的面试题——HashSet和HashMap的区别。HashSet基于HashMap实现,存储唯一值;HashMap存储键值对。两者在数据结构、使用场景、操作方法等方面有显著差异。HashSet无序且依赖元素的hashCode和equals方法保证唯一性,而HashMap需注意线程安全问题。掌握这些知识点,助你轻松应对面试。更多技术干货,欢迎关注我的微信公众号“软件求生”。
592 4
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
存储 Java 程序员
Java面试加分点!一文读懂HashMap底层实现与扩容机制
本文详细解析了Java中经典的HashMap数据结构,包括其底层实现、扩容机制、put和查找过程、哈希函数以及JDK 1.7与1.8的差异。通过数组、链表和红黑树的组合,HashMap实现了高效的键值对存储与检索。文章还介绍了HashMap在不同版本中的优化,帮助读者更好地理解和应用这一重要工具。
1043 5

热门文章

最新文章