Java学习-Hashmap

Java HashMap是基于哈希表的Map实现。 这就是为什么面试官总是要求HashMapHashTable之间存在差异的原因。 HashMap基本上等于HashTable,但以下两个区别除外。

  1. HashTable同步时,HashMap不同步。
  2. HashMap允许为null,而HashTable不允许为null

HashMap的重要属性

DEFAULT_INITIAL_CAPACITY默认初始容量(2 的 n 次幂)。 HashMap可以包含许多元素。
MAXIMUM_CAPACITYHashMap的最大容量(2 的 n 次幂)。
loadFactor定义HashMap的阈值。 重新调整大小时将在HashMap中发生。
DEFAULT_LOAD_FACTORHashMap的构造器中未定义任何负载因子时将使用。
sizeHashMap包含的键/值对映射数。

创建HashMap

在创建HashMap时未定义任何参数时,将使用默认的初始容量(16)和默认的负载系数(0.75)。 该HashMap最多可以包含 16 个元素,并且在插入第 13 个元素时会调整HashMap的大小。 这是因为负载系数为 75% (.75),并且在添加第 13 个元素(12 + 1)时将超过此阈值。

您还可以提供初始容量和loadFactor。 但是初始容量不能超过最大容量(2 的 30 次幂),并且负载系数不能为零或负数。

HashMap中元素的添加

为了添加一个元素,您需要提供 2 个东西:键和值。

:将与指定值关联的键。 null是允许的。

:与指定键关联的值。

首先,HashMap将为给定键生成一个哈希码,然后检查是否已经有与给定键相关联的值。 如果是,则它将返回已经关联的值。 否则,它将通过提供的键在HashMap中增加值。

重点

  1. HashMap不会按Map中的元素顺序提供任何保证(均值顺序会随时间变化)。
  2. HashMap获得设置操作提供恒定时间性能(如果使用正确的哈希算法)。
  3. 迭代集合所需的时间与HashMap的“容量”(它可以容纳的元素)和大小(它当前容纳的元素)成比例。
  4. 如果迭代性能更为重要,那么建议不要将初始容量设置得太高而将负载系数设置得太低。 由于性能与初始容量负载系数成正比。
    • 容量是哈希表中的存储桶数。
    • 初始容量(默认值为 16)只是创​​建哈希表时的容量。
    • *负载因子(默认值 .75)*是衡量哈希表在自动增加其容量之前的填充程度的度量。
    • 当哈希表中的条目数超过负载因子与当前容量的乘积时,哈希表将被重映射(即内部数据结构将被重建)。
  5. 使用“Collections.synchronizedMap()”方法使映射同步。
  6. HashMap类返回的迭代器为“故障快速”。
  7. HashMap由数组(Key)和LinkedListValue)支持。
  8. HashMap使用hashcode(使用键)来标识应在HashMap中放置或检索对象的确切位置。
  9. 最后,HashCode返回后备数组中的确切位置(索引)。
  10. 支持数组的大小固定。 因此,只要数组已满(此映射中的键数达到其阈值)。 将创建一个具有新容量的新数组,并将所有元素添加到该新数组中。
  11. 在两种情况下(添加和检索对象)都将使用HashCode,而在任何情况下均可以使用或可以不使用equals()方法。
  12. HashMapKey的最佳候选者是具有正确实现EqualsHashcode方法的不可变类(示例:字符串类)。
  13. 更好的哈希码和equals方法实现是HashMap的更好性能。
  14. 这样,所有String和原始类型的包装类将是HashMap中键的理想选择。

什么是重新哈希

每个HashMap都有预定义的大小(初始容量),以及在需要时(超过阈值限制时)增加此大小(负载系数)的逻辑。

示例

使用以下配置创建HashMap

初始容量:16(默认初始容量

负载系数:.75(默认负载系数

在给定的HashMap中添加第 13 个元素后,超过给定HashMap的阈值限制,系统将创建一个新的后备键集数组(此数组的大小将是前一个数组的两倍)。 系统将不得不再次计算确切的存储桶,应放置上一个存储桶中的元素,并将旧HashMap中的所有元素复制到新的HashMap中。 整个过程称为重新哈希,因为会再次为每个元素计算Hashcode

因为超时的HashMap可能会被重新散布并且顺序可能会发生变化。

HashMap的示例

在此示例中,您将学到以下几点

  1. 如何迭代映射
  2. 迭代映射的不同方法
  3. HashCodeEquals何时被调用。 (请特别注意HashCode的输出和equals方法调用)
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapExample {
    public static void main(String[] args) {
        Map<JBT, Integer> m1 = new HashMap<JBT, Integer>();
        JBT t1 = new JBT(1, 2);
        JBT t2 = new JBT(1, 3);
        JBT t3 = new JBT(2, 1);
        m1.put(t1, 1);
        m1.put(t2, 2);
        m1.put(t3, 3);
        System.out.println("Addition Done");
        /*
         * Below you can find 3 different ways to iterate a Map. Uncomment
         * different section and see the different in Output. Pay attention to
         * when Hashcode and Equals is called
         */
/*        Set s = m1.entrySet();
        for (Iterator i = s.iterator(); i.hasNext();) {
            Map.Entry me = (Map.Entry) i.next();
            System.out.println(me.getKey() + " : " + me.getValue());
        }
*/
/*        for (Map.Entry<JBT, Integer> entry : m1.entrySet()) {
            System.out.println("Key : " + entry.getKey() + " Value : "
                    + entry.getValue());
        }
*/
        for (Object key : m1.keySet()) {
            System.out.println("Key : " + key.toString() + " Value : "
                    + m1.get(key));
        }
    }
}
class JBT {
    JBT(int i, int j) {
        this.i = i;
        this.j = j;
    }
    int i, j;
    @Override
    public int hashCode() {
        System.out.println("Inside HashCode Method");
        int k = i + j;
        return k;
    }
    @Override
    public boolean equals(Object obj) {
        System.out.println("Inside Equals Method");
        if (i == ((JBT) obj).i && j == ((JBT) obj).j)
            return true;
        else
            return false;
    }
    @Override
    public String toString() {
        return String.valueOf(i).concat(String.valueOf(j));
    }
}

原文链接:Java HashMap Tutorial for beginners

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Da白兔萘糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值