JavaSE-15.1.3【HashSet集合的特点和保证元素唯一性的原理、常见数据结构之哈希表】
1 package day6.lesson1; 2 3 import java.util.HashSet; 4 5 /* 6 1.3 HashSet集合的特点 7 8 底层数据结构是哈希表 9 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致 10 没有带索引的方法,所以不能使用普通for循环遍历(但可以使用迭代器和增强for进行遍历) 11 由于是Set集合,所以是不包含重复元素的集合 12 13 1.4 HashSet集合保证元素唯一性的原理 14 15 图示 16 17 1.根据对象的哈希值计算存储位置 18 如果当前位置没有元素则直接存入 19 如果当前位置有元素存在,则进入第二步 20 2.当前元素的元素和已经存在的元素比较哈希值 21 如果哈希值不同,则将当前元素进行存储 22 如果哈希值相同,则进入第三步 23 3.通过equals()方法比较两个元素的内容 24 如果内容不相同,则将当前元素进行存储 25 如果内容相同,则不存储当前元素 26 27 总结:HashSet集合存储元素时要保证元素唯一性需要重写hashCode() & equals() 28 29 1.5 常见数据结构之哈希表 30 31 JDK8之前,哈希表采用数组+链表实现,即一个元素为链表的数组 32 JDK8以后,在长度较长时,底层实现了优化 。。。 33 34 哈希表图示,证明如何保证元素唯一性 35 */ 36 public class HashSetDemo3 { 37 public static void main(String[] args) { 38 HashSet<String> hs = new HashSet<>(); 39 hs.add("hello"); 40 hs.add("world"); 41 hs.add("world"); 42 hs.add("java"); 43 hs.add("java"); 44 System.out.println(hs); //[world, java, hello] 45 for (String str: hs){ 46 System.out.println(str); 47 } 48 /* 49 world 50 java 51 hello 52 */ 53 54 /* 55 //add()溯源 56 public boolean add(E e) { 57 return map.put(e, PRESENT)==null; 58 } 59 public V put(K key, V value) { 60 return putVal(hash(key), key, value, false, true); 61 } 62 static final int hash(Object key) { 63 int h; 64 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 65 } 66 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, 67 boolean evict) { 68 Node<K,V>[] tab; //元素为节点的数组,哈希表 69 Node<K,V> p; 70 int n, i; 71 if ((tab = table) == null || (n = tab.length) == 0) 72 n = (tab = resize()).length; 73 if ((p = tab[i = (n - 1) & hash]) == null) 74 tab[i] = newNode(hash, key, value, null); 75 else { 76 Node<K,V> e; K k; 77 if (p.hash == hash && 78 ((k = p.key) == key || (key != null && key.equals(k)))) 79 e = p; 80 else if (p instanceof TreeNode) 81 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); 82 else { 83 for (int binCount = 0; ; ++binCount) { 84 if ((e = p.next) == null) { 85 p.next = newNode(hash, key, value, null); 86 if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st 87 treeifyBin(tab, hash); 88 break; 89 } 90 if (e.hash == hash && 91 ((k = e.key) == key || (key != null && key.equals(k)))) 92 break; 93 p = e; 94 } 95 } 96 if (e != null) { // existing mapping for key 97 V oldValue = e.value; 98 if (!onlyIfAbsent || oldValue == null) 99 e.value = value; 100 afterNodeAccess(e); 101 return oldValue; 102 } 103 } 104 ++modCount; 105 if (++size > threshold) 106 resize(); 107 afterNodeInsertion(evict); 108 return null; 109 } 110 */ 111 } 112 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!