JAVA——HashMap & HashSet 相关知识总结

        首先,我们了解 Map , Set 以及 哈希表 是什么。

        Map和set是一种专门用于进行搜索的容器或数据结构,其搜索的效率与其具体实例
化的类有关(适于动态查找)
模型:
        一般把搜索的数据称为关建字(key),和关键值对应的称为值(value),将其称为 Key-Value 键值对
        所有模型有两种
                ①纯key模型 :TreeSet (基于二叉搜索树),HashSet (基于哈希表)
                eg:有一个字典,查一个单词是否在字典中。
                ⑫Key - Value模型: Tree Map(基于二叉搜索树), HashMap (基于哈希表)
                eg 统计文章中对应词出现的词数 <词,对应次数>
        Map 中存放Key-Value键值对, Set中只存放Key

        Map是一个接口,该类没有继承自Collection,存储<K,V>结构的键值对,且K唯一,不能重复。
        Map 常用方法
        V get (Object key)        返回 key对应的v


        V get OrDefault (Object key, V default value) 若key存在,返回对应value。否则,返回默认值


        V put (K key,Vvalue)  设置Key对应的value 


        V remove (object key)  删除key对应的映射关系


        boolean containsKey (Object key)   判段是否含有 key


        boolean containsValue (Object value)    判断是否含有 value


        Set<k>   keySet()       返回所有key的不重复集合。

        Collection <V>    values()        返回所有value的可重复集合        

        Set<Map. Entry<K,V>>    entrySet()  返回所有 key-value 映射关系

需要注意的是:

①Map是一个接口,不可直接实例化,只实例其实现类 TreeMap or HashMap
② Map 中 key 唯一, value 可重复
③ TreeMap中插入键值对时, key不为空,否则的空针异,但由value 可为空。而 HashMap中 key 可以为 null,但只能放一个。
④ Map中的Key可以全部分离出来,存到set中进行访问(因为key不能重复)
⑤ Map中Value  存到Collection的任何一个集中(value可有重复)
⑥ Map中键值对的key不能直接改,若要改,只能先删,再重新插入

Map Entry<K,V> 是Map内部实现的用来存放键值对映射关系的内部类,其主
要提供了
K getKey ()  
V getValues()
V setValue( V value)
并没有设置K的方法。

TreeMap 与 HashMap 的区别

        Set  是继承自 Collection 的接口类,只能存key
        常见方法
        bodean add (E e)        添加,重复的不添
        void  clear()        清空Set
        boolean  contains (Object o)        判 o 是否存在
        Iterator<E>  iterator ()        返回迭代器
        boolean  remove (Object o)           移除
        int size()        返回存放的元素个数
        boolean isEmpty()        判断是否为空
        Object[ ]  toArray()        以数组的形式返回    
        boolean containsAll (Collection <?>  c)        判断集合 c 中的元素是否在 Set 中全部存在。若全存,返回 true。否则,返回 false。        
        boolean addAll(Collection<? extends E>C)         将集合 c 中的元素添加到 Set 中,由于 Setkey 不重复,所以可以实现去重的效果。

注:

1.Set是继承自Collation的一个接口类
2.Set 的底层使用 Map 实现,其使用KeyObject的一个默认对象作为键值对插入Map
3.Set 最大功能——对集合元素去重
4.实现Set接的常用类有TreeSet, HashSet 还有LinkedHashSet.
LinkedHashSet 是在HashSet的基础上维护了一个双向链表来记录插入次序
6.Set的修改同Map
7.TreeSet中不存 为 null key,而 HashSet中可以,但也只能存一个。


        TreeSet HashSet 的区别:    同TreeMapHashMap的区别,只存在一点不同——HashSet 不一定有序。

       

 哈希表 :不经比较,可以直接得到所要元素。它构造一种存储结构,通过函数使元素所在
位置与关键码能建立一一映射关系(就像水浒传中 角色的外号,一提到豹子头 就知道是林冲。)即哈希法又称(散列法)
常见哈希函数:
        hash (key) = key % Capacity(数组长度)通过对 key 取余得到其对应的地址,放入其中。取出时, 在通过该函数得出地址直接取出,无需比较。
        (碰撞)冲突:经哈函得相同地址。        具有不同关建码而且有相同哈地的元素,称为“同义词”。(冲突是不可避免)
        减少或降低冲突的的方法主要有

设计合理的哈希函数
        哈函设计原则:①定义域必须包括需存储的全部建码,而如果散列表有 m 个地址时,
其值域必须在0到m-1之间
                         ②经计算所得地址均匀分布
                         ③比较简单

        常见哈函

        ①直接定制法(常用) 地址: Hash(Key)=A*Key + B
        优点:简单,均匀        

        缺点:需事先知道关键字的分布情况

        场景:适合查较小,连续的情况


        ②除留余数法-(常用) 地址: Hash(Key)=Key%P(P≤m)
        m分散列表中允许的地址数,P为 <= m 且最接近或等于m的质数
        ③平方取中法④折叠法⑤随机数作地址 ⑥数学方法

        注:哈函越精密,产生活中可能性越小,但无法避免
调节负载因子

        负载因子 = 元素个数 / 哈表长度           这个值一般要求 <= 0.75

        通过哈表长度调节负载因子

闭散列也叫开放址法        当冲突时,若表未满则存在“下一个空位置
        1.线性探测,从冲突位向后探测,直到寻找到下一个空位置
        采用闭散列处理冲突时,不能随便物理删除已有元素,会影响其他元素
的搜索。因此线探采用标计的伪删除法来删除一个元素
        2.二次探测:

        hi​=(h(key)+c1*​i+c2*​i^2)%m。这里c1​和c2​是常数,i是探测次数。与线性探测法不同,二次探测法以二次函数的方式来确定下一个探测位置,这样可以减少聚集现象,使元素在哈希表中分布得更均匀。例如,取c1​=1,c2​=1,h(key)=3,m=11,第一次冲突时i=1,则h1​=(3+1×1+1×12)%11=5,即探测位置5。
        闲散列最大缺陷空间利用率低,这也是哈希的缺陷。
开散列  一个地址对应一个单链表

        如图所示:


通常认为哈希表的插/删/查的时复为O(1)

        使用示例:

package bit_0719;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class T1_0410 {
 public static void main(String[] args) {
    // HashMap示例
    Map<String, Integer> hashMap = new HashMap<>();
    
    // 添加元素
    // put(K key, V value): 将指定键值对存入HashMap
    // 如果键已存在,则替换对应的值
    hashMap.put("Apple", 10);
    hashMap.put("Banana", 5);
    hashMap.put("Orange", 8);
    
    // 获取元素
    // get(Object key): 返回指定键所映射的值,如果键不存在则返回null
    System.out.println("Apple的数量: " + hashMap.get("Apple"));
    
    // 判断键是否存在
    // containsKey(Object key): 检查HashMap中是否包含指定的键
    System.out.println("包含Banana: " + hashMap.containsKey("Banana"));
    
    // 删除元素
    // remove(Object key): 删除指定键对应的键值对
    hashMap.remove("Orange");
    
    // 遍历HashMap
    // entrySet(): 返回HashMap中所有键值对的Set集合
    System.out.println("\nHashMap内容:");
    for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
        System.out.println(entry.getKey() + ": " + entry.getValue());
    }
    
    // 获取HashMap大小
    // size(): 返回HashMap中键值对的数量
    System.out.println("\nHashMap大小: " + hashMap.size());
    
    // 批量添加元素
    // putAll(Map<? extends K, ? extends V> m): 将指定Map中的所有键值对复制到此HashMap中
    Map<String, Integer> moreFruits = new HashMap<>();
    moreFruits.put("Grape", 15);
    moreFruits.put("Peach", 7);
    hashMap.putAll(moreFruits);
    System.out.println("\n批量添加后的HashMap:");
    hashMap.forEach((k,v) -> System.out.println(k + ": " + v));
    
    // 清空HashMap
    // clear(): 移除HashMap中所有键值对
    hashMap.clear();
    System.out.println("\n清空后的HashMap大小: " + hashMap.size());
    
    // HashSet示例
    Set<String> hashSet = new HashSet<>();
    
    // 添加元素
    // add(E e): 将指定元素添加到HashSet中,如果元素已存在则返回false
    hashSet.add("Red");
    hashSet.add("Green");
    hashSet.add("Blue");
    
    // 判断元素是否存在
    // contains(Object o): 检查HashSet中是否包含指定元素
    System.out.println("\n包含Green: " + hashSet.contains("Green"));
    
    // 删除元素
    // remove(Object o): 从HashSet中移除指定元素
    hashSet.remove("Blue");
    
    // 遍历HashSet
    System.out.println("\nHashSet内容:");
    for (String color : hashSet) {
        System.out.println(color);
    }
    
    // 获取HashSet大小
    // size(): 返回HashSet中元素的数量
    System.out.println("\nHashSet大小: " + hashSet.size());
    
    // 批量添加元素
    // addAll(Collection<? extends E> c): 将指定集合中的所有元素添加到HashSet中
    Set<String> moreColors = new HashSet<>();
    moreColors.add("Yellow");
    moreColors.add("Purple");
    hashSet.addAll(moreColors);
    System.out.println("\n批量添加后的HashSet:");
    hashSet.forEach(System.out::println);
    
    // 清空HashSet
    // clear(): 移除HashSet中所有元素
    hashSet.clear();
    System.out.println("\n清空后的HashSet大小: " + hashMap.size());
    
    // 测试更多Map方法
    hashMap.put("Apple", 10);
    hashMap.put("Banana", 5);
    // getOrDefault(Object key, V defaultValue): 获取指定键对应的值,如果键不存在则返回默认值
    System.out.println("\n测试getOrDefault: " + hashMap.getOrDefault("Pear", 0));
    // containsValue(Object value): 检查HashMap中是否包含指定的值
    System.out.println("测试containsValue: " + hashMap.containsValue(5));
    
    // keySet(): 返回HashMap中所有键的Set集合
    System.out.println("\n所有key: " + hashMap.keySet());
    // values(): 返回HashMap中所有值的Collection集合
    System.out.println("所有value: " + hashMap.values());
    // entrySet(): 返回HashMap中所有键值对的Set集合
    System.out.println("所有entry: " + hashMap.entrySet());
    
    // 测试更多Set方法
    hashSet.add("Red");
    hashSet.add("Green");
    
    // iterator(): 返回此集合中元素的迭代器
    System.out.println("\nSet迭代器测试:");
    Iterator<String> it = hashSet.iterator();
    while(it.hasNext()) {
        System.out.println(it.next());
    }
    
    // toArray(): 返回包含此集合中所有元素的数组
    System.out.println("\nSet转数组: " + Arrays.toString(hashSet.toArray()));
    
    Set<String> testSet = new HashSet<>();
    testSet.add("Red");
    testSet.add("Blue");
    // containsAll(Collection<?> c): 检查HashSet是否包含指定集合中的所有元素
    System.out.println("测试containsAll: " + hashSet.containsAll(testSet));
    
    // isEmpty(): 检查HashSet是否为空
    System.out.println("测试isEmpty: " + hashSet.isEmpty());
 }
}

       运行结果:

Apple的数量: 10
包含Banana: true

HashMap内容:
Apple: 10
Banana: 5

HashMap大小: 2

批量添加后的HashMap:
Apple: 10
Grape: 15
Peach: 7
Banana: 5

清空后的HashMap大小: 0

包含Green: true

HashSet内容:
Red
Green

HashSet大小: 2

批量添加后的HashSet:
Red
Yellow
Purple
Green

清空后的HashSet大小: 0

测试getOrDefault: 0
测试containsValue: true

所有key: [Apple, Banana]
所有value: [10, 5]
所有entry: [Apple=10, Banana=5]

Set迭代器测试:
Red
Green

Set转数组: [Red, Green]
测试containsAll: false
测试isEmpty: false

       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值