hash(散列)?
散列数据结构,但是java这里屏蔽了,直接就用封装的形式把他封装到了 HashSet,HashMap,HashTable中.其中HashTable已经过时了.
hash算法:java中指的hashCode()函数及其重写.
目标:给每个对象生成一个唯一的标示符
根据对象的特点为每个对象生成一个唯一hashCode,然后把这个hashCode作为下标,把对象值作为元素值保存到数组中(对象的引用).这个时候这个数组就可以看做关联数组.java中没有关联数组这个概念,单独取了个名叫HashSet.
Hash的过程:
拿到对象,调用他自己的hash算法(hashCode()方法),生成一个唯一的hash值,然后把这个值保存到数组中,整个过程就是hash.数组,和唯一值,和对象的关系,我们就叫HashSet;
hash算法在java中就是指Object中的hashCode()函数里面的算法,这一个是根据你写的类来自己定义的.
hash哈希冲突:多个对象可能生成一个相同的hash值.
HashSet为什么无序,不可重复?
1 生成的hashCode没有一定大小关系,就无所谓顺序
2 每个对象都必须生成一个唯一的hashCode(多个对象可以生成相同的,但是还要比较值),如果是重复的对象,肯定是生成同一个hashCode,并且值也是相同的.这个时候就没有办法唯一性查询出某个数据.所以必须是不可重复的.所有的一切为了数据的唯一标识.
HashSet和HashMap
1 HashSet 是HashMap的一个实现,本质是HashMap.而HashMap的数据结构是一个Hash表.
2 Hash表又叫散列表,其底层是通过hashCode()函数组成的一个数组,每个数组的元素又是一个单向链表.每个单项链表都有一个独一无二hash值,就是数组的下标,也意味着每个单项链表的节点的hash值是相同的.
怎么向Hash表中添加元素.
1) 要添加的时候,HashMap保存的是映射关系,这个映射关系靠什么来维护(Map.Entry(K,V)),是一个接口,那我们就可以传入各种对象的映射关系.如果生成了重复的hash值怎么办?就会往HashTable,桶位上加一个单向链表单向链表中每个对象都是一个Entry.
重点:2) 添加过程: 第一步:先调用要存储的映射关系的key对象,然后调用key对象自身的hashCode()方法,生成hash码,向数组中添加元素.如果没有这个hash码,就占用一个数组的空间,保存这个key-value映射对象Entry.如果已经有了这个hash码,就需要执行第二步.
第二步:equals(),把键的值挨个在hash码相同的链表中进行比较,如果返回为true那么就代表该链表中已经有了这个key值,就放弃添加,如果没有则返回false,就执行第三步.
第三步:就把数组中当前保存的那个节点向后移动一位(并不是真的移动,只是我取得他内存地址,保存在新加入的那个元素的nextNode中),再把当前的这个映射关系对象Entry保存到数组中.
3) HashSet和Hashmap 初始化容量都是16,默认加载因子都是0.75.
索引数组:在内存空间上是连续的记数也是连续的,总体就是有序的
关联数组:在内存空间上是连续的,记数不是连续的,就是无序的
哈希表:用hashCode()函数进行编码的作为下标的关联数组.
我们用的hashCode()函数可能会有重复的情况,但是数组又规定不能重复,我们再用equals()比较另外一个外属性(必须包含两个比较,一个比较hashCode,另外一个比较另外一个属性.)
hashSet:只保存了一个元素.
hashMap:是一个元素里面保存两个对象的映射关系,再把这个映射关系封装成一个对象