0
点赞
收藏
分享

微信扫一扫

DVWA 靶场 JavaScript 通关解析

田妞的读书笔记 2024-06-28 阅读 25

数据结构与算法-Hash算法-2

5 HashMap(又双叒叕提到红黑树动态扩容)

由于链表这种结构确实存在一些缺点,所以在我们的JDK中对之进行了优化,引入了更高效的数据结构:红黑树

  1. 初始大小:HashMap默认的初始大小是16,这个默认值是可以设置的,如果事先知道大概的数据量有多大,可以通过修改默认初始大小,减少动态扩容的次数,这样会大大提高HashMap的性能。

  2. 动态扩容:最大装载因子默认是0.75,当HashMap中元素个数超过0.75*capacity(capacity表示散列表的容量)的时候,就会启动扩容,每次扩容都会扩容为原来的两倍大小。

  3. Hash冲突解决办法:JDK1.7底层采用链表法。

    在JDK1.8版本中,为了对HashMap做进一步优化,我们引入了红黑树。而当链表长度太长(默认超过8)时,链表就转换为红黑树。我们可以利用红黑树快速增删改查的特点,提高HashMap的性能。当红黑树结点个数少于8个的时候,又会将红黑树转化为链表。因为在数据量较小的情况下,红黑树要维护平衡,比起链表来,性能上的优势并不明显。

  4. Hash函数:JDK的hash函数非常经典,建议大家收藏,以后都可以用。

    int hash(Object key) {
     int h = key.hashCode()return (h ^ (h >>> 16)) & (capitity -1); //capicity表示散列表的大小,最好使用2的整数倍
    }
    

6 如何设计Hash

假如你在面试中碰到了要你如何设计一个高效的企业级Hash表。你该如何处理?

这里大家可以借鉴HashMap 的设计思路:

  1. 必须要高效:即插入,删除 查找必须要快
  2. 内存:不能占用太多的内存,考虑用其他的结构,比如B+Tree,HashMap 10亿,存硬盘的算法:mysql B+tree
  3. Hash函数:这个要根据实际情况考虑.%
  4. 扩容:就是预估数据的大小,HashMap 默认的空间是16? 我知道我要存10000个数,2^n > 10000 or 2^n-1
  5. Hash冲突后怎么解决:链表 数组。

7 Hash的应用

  1. 加密:MD5 哈希算法。还是存在密码冲突 128位的二进制串,可以表示2^128次,md5(md5(),”1231”),b不可逆,建了一个hash库,存起来了。 Md5(88888888),穷举

  2. 怎么判断视频是否是重复的?Md5();128位

  3. 相似性检测:论文检测,指纹算法。会把每个论文计算出一个指纹,汉明距离。

  4. 负载均衡:nginx,2台服务器;可以根据ip计算hash,再做一个取模2运算。

  5. 分布系统:数据分库问题。我不是讲过一个10亿的数据的搜索词,一台机器存不下。要分成10个文件。Hash(key)%10 = > 就可以知道某个key在哪一个文件?扩大成数据库的 分表(10张表) id%10 =()。

  6. 分布式存储的时候:问题来了 如果我加了一张表。原来是10张,现在是11张了 怎么办?要重新计算,分配的时候查询怎么办?数据量很大,迁移的不是太多了吗?

  7. 查找算法:hashMap 查找如何设计出自己的一个hash查找算法呢?快,hash冲突要少,数据大小。初始大小,扩容

  8. 一致性Hash:哈希环

    假设我们有k个表,数据的hash值范围:[0,Integer.max].我们把整个数据范围划分成n个区间(n个区间要远远大于我们的k),每一个表就是分配到n/k的区间。当有新的表要来了,我们只需要将某几个小的区间数据迁移就可以了。这是一个环形结构,其根本思想就是分段了。

重点部分:数组 链表 二叉树 红黑树 HashMap源码

8 HashMap源码(又双叒叕)

  1. 构造方法:

    HashMap<Integer, String> map = new HashMap<>(); // 创建一个空的HashMap
    HashMap<Integer, String> mapWithCapacity = new HashMap<>(16); // 创建一个预设容量的HashMap
    
  2. put方法:

    map.put(1, "Apple"); // 添加键值对
    
  3. get方法:

    String value = map.get(1); // 获取键对应的值
  4. equals方法:

    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof Map))
            return false;
        Map<?,?> m = (Map<?,?>) o;
        if (m.size() != size())
            return false;
        try {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                K key = e.getKey();
                V value = e.getValue();
                if (value == null) {
                    if (!(m.get(key)==null && m.containsKey(key)))
                        return false;
                } else {
                    if (!value.equals(m.get(key)))
                        return false;
                }
            }
        } catch (ClassCastException unused) {
            return false;
        } catch (NullPointerException unused) {
            return false;
        }
        return true;
    }
    
  5. remove方法:

    String removedValue = map.remove(1); // 移除键值对并返回值
    
  6. size方法:

    int size = map.size(); // 获取HashMap的大小
    
  7. isEmpty方法:

    boolean isEmpty = map.isEmpty(); // 检查HashMap是否为空
    
  8. containsKey方法:

    boolean contains = map.containsKey(1); // 判断HashMap是否包含键1
    
  9. containsValue方法:

    boolean containsValue = map.containsValue("Apple"); // 检查HashMap中是否包含指定值
    
  10. keySet方法:

    Set<Integer> keySet = map.keySet(); // 获取HashMap中所有键的Set视图
    
  11. values方法:

    Collection<String> values = map.values(); // 获取HashMap中所有值的Collection视图
    
  12. entrySet方法:

    Set<Map.Entry<Integer, String>> entrySet = map.entrySet(); // 获取HashMap中所有键值对的Set视图
    
  13. clear方法:

    map.clear(); // 清空HashMap中的所有键值对
    
  14. hashCode方法:

    Collection<String> values = map.values(); // 获取HashMap中所有值的Collection视图
    
  15. clone方法:

  16. hash方法(用于自定义对象作为键时):

    public class MyKey {
        int value;
        // 必须重写hashCode方法
        @Override
        public int hashCode() {
            return Objects.hash(value);
        }
        // 必须重写equals方法
        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
            MyKey myKey = (MyKey) obj;
            return value == myKey.value;
        }
    }
    

    注意:以上代码示例假设IntegerString是键和值的类型,实际使用时可以替换为任何实现了equals()hashCode()方法的对象。

举报

相关推荐

0 条评论