目录
1.常用方法
2.遍历
3.内存结构
4.扩容方式
5.Map的其他实现类
HashMap<K,V>是最常用的一种map,在其内部包装了一个Node<K,V>的类,并且用Node型的数组table用来存储数据,与ArrayList一样的实现了元素的增删以及扩容等功能.K一般是8中基本类型的封装类和String类,可存储null的键和null的值.
1.常用方法
add() addAll() |
增加元素 |
remove() clear() |
删除元素 |
size() isEmpty() get() equals() |
元素的数量 是否为空 返回指定键所映射的值 是否为同一个HashMap |
containsKey() containsValue() |
是否包含指定的键 是否包含指定的值 |
keySet() values() entrySet() |
返回所有键的Set 返回所有值的Collection 返回所有映射的Set |
2.遍历
根据HashMap提供的方法,可以分别得到V的集合,K的集合,V和K映射关系的集合.
public class HashMapDemo2 { public static void main(String[] args) { HashMap<String, Integer> map = new HashMap<>(); map.put("a", 12); map.put("b", 34); map.put("c", 56); map.put("d", 78); map.put("a", 90);// 覆盖("a", 12) map.put("d", 10);// 覆盖("d", 78) map.put(null, 22);// 可存储空K map.put(null, 30);// 覆盖原空K // toString重写,直接打印 System.out.println(map); // 通过keySet()方法返回K的Set Set<String> kSet = map.keySet(); for (String value : kSet) { System.out.println(value); } // 通过values()方法返回V的Collection Collection<Integer> vSet = map.values(); for (Integer value : vSet) { System.out.println(value); } // 通过entrySet()方法返回Entry的Set Set<Map.Entry<String, Integer>> entrySet = map.entrySet(); for (Entry<String, Integer> value : entrySet) { System.out.println(value); } } }
3.内存结构
1)HashMap中的table并不是按自然顺序索引来存储每一个Node<K,V>的,同一索引处可以存储不止一个Node<K,V>,这是由Node<K,V>的属性决定的.
2)Node<K,V>除了K和V之外,还有一个int类型的hash属性,和自身类型的next属性.hash属性是通过内部算法得到的Node对象的哈希值,通过对hash进行计算(hash%table.length)确定其在table中存储的索引,如果此处为空,则next属性指向null;如果此处已经有了一个Node,则当前元素的next指向之前的Node,并且把自身存储在当前位置.
3)通过这种分组散列的存储方式,在每次添加新元素时,只需在对应组内比较是否具有相同元素,提高了HashMap的遍历性能.
4)HashMap对于重复元素的判断和HashSet是有区别的:"=="和equals()方法是针对K进行判断的.(HashSet只是通过HashMap的K实现的)
5)对于添加的重复元素,HashMap保留旧的键K,替换新的值V.(所以HashSet中会保留旧的元素)
public class HashMapDemo3 { public static void main(String[] args) { HashMap<String, Integer> map = new HashMap<>(); map.put("a", 12); map.put("b", 34); map.put("c", 56); map.put("d", 78); map.put("a", 90);// 覆盖("a", 12) map.put("d", 10);// 覆盖("d", 78) map.put(null, 22);// 可存储空K map.put(null, 30);// 覆盖原空K System.out.println(map); } }
运行结果:{null=30, a=90, b=34, c=56, d=10}
4.扩容方式
1)HashMap的构造函数可以传入两个参数,容量capacity(table数组的长度,默认16)和加载因子loadFactor(默认0.75),通常情况下loadFactor小于1.
2)HashMap的capacity必须满足是2的N次方,如果在构造函数内指定的容量n不满足,HashMap会通过下面的算法将其转换为大于n的最小的2的N次方数.
// 减1→移位→按位或运算→加1返回 static final int tableSizeFor(int cap) { int n = cap - 1; n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; }
3)当满足(size > capacity * loadFactor)时,HashMap会执行扩容操作,每次扩容<<1.这里存在一个问题,如果loadFactor被错误的定义为远大于1的数,那么当元素个数大于capacity时,HashMap会如何处理呢?例:
public class HashMapDemo4 { public static void main(String[] args) throws Exception { HashMap<String, Integer> map = new HashMap<>(1, 100000);// 设置扩容临界1*100000 Class c = Class.forName("java.util.HashMap"); Field f = c.getDeclaredField("table"); f.setAccessible(true); Object[] data = null; // 添加2000个元素并打印输出size和capacity for (int i = 0; i < 2000; i++) { map.put(new Integer(i).toString(), i); data = (Object[]) f.get(map); System.out.println("size:" + map.size()+"\tcapacity:" + data.length); } } }
运行结果:
size:1 capacity:1
size:2 capacity:1
size:3 capacity:1
size:4 capacity:1
size:5 capacity:1
size:6 capacity:1
size:7 capacity:1
size:8 capacity:1
size:9 capacity:2
size:10 capacity:2
.....
size:2000 capacity:64
可以看到,HashMap并不只是依据上述条件而进行扩容,当元素达到一定数量(8)时即使不满足(size > capacity * loadFactor),也会主动扩容到一个默认的"最小扩容量"64.其内部的关键代码:
// put方法间接调用 if (binCount >= TREEIFY_THRESHOLD - 1) treeifyBin(tab, hash); // treeifyBin内部代码 if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) resize();
TREEIFY_THRESHOLD是HashMap定义的常量8.
MIN_TREEIFY_CAPACITY是HashMap定义的常量64,即最小扩容量.
5.Map的其他实现类
1)Hashtable
基于Dictionary的旧类.与HashMap不同点:线程安全,V和K都不能为null;默认容量11,扩容方式*2+1.
2)TreeMap
内部通过二叉树结构存储数据,排序存储,可在构造时自定义Comparator按指定规则存储.
相关推荐
"Java集合框架面试题" Java 集合框架是 Java 语言中的一组预定义类和接口的集合,用于存储和操作数据。下面是 Java 集合框架的知识点总结: 1. Java 集合类主要有两大分支:Collection 接口和 Map 接口。...
在这个主题中,我们将深入探讨HashMap类,它是Java集合框架中的一个关键组件,特别是在标题“20-集合框架020-HashMap-1080P 高清-AVC20”和描述中所提到的内容。 HashMap是Java.util包中的一个类,它实现了Map接口...
HashMap和HashSet都是Java集合框架的重要组成部分,它们分别提供了键值对的存储和无序唯一元素的存储。在实际编程中,HashMap常用于快速查找、存储和更新关联数据,而HashSet则常用于去除重复元素。理解并熟练运用这...
Java集合框架广泛使用了泛型,如`ArrayList<T>`、`HashMap<K, V>`等。使用泛型可以确保添加到集合中的元素类型正确,避免了强制类型转换的需要。 总结,Java中的泛型是提高代码质量和可维护性的重要工具。理解和...
泛型在Java集合框架中得到了广泛的应用,例如`ArrayList<E>`、`HashMap<K, V>`等。此外,它也用于接口(如`Comparable<T>`)、枚举(`EnumSet<E>`)、方法返回类型以及匿名类等场景。 总的来说,Java泛型提供了一种...
Java集合框架是Java编程语言中一个非常重要的组成部分,它提供了一组高级的数据结构,使得开发者可以更加方便地存储和管理对象。这个框架的核心是几个关键的接口,包括`Collection`、`Set`、`List`和`Map`,以及一些...
Java 集合框架是 Java 语言中最重要的一部分,掌握集合框架可以让开发者更好地进行 Java 编程。下面将详细介绍 Java 集合框架的实现原理和使用方法。 1.1 集合框架概述 Java 集合框架是 Java 语言中用于存储和操作...
6. Map支持泛型,形式如:Map<K,V>。 在JAVA集合框架中,HashMap是Map的一个重要实现类,也是最常用的,基于哈希表实现。HashMap的特性包括: 1. HashMap基于哈希表实现。 2. HashMap中的Entry对象是无序排列的。 ...
Collection接口是Java集合框架的根接口,定义了基本的集合操作,而Map接口继承自Collection接口,提供了键值对的存储和操作。 Collection接口 Collection接口是Java集合框架的根接口,定义了基本的集合操作,包括...
Java集合框架是Java编程语言中一个非常重要的概念,它提供了一组高级的数据结构,使得开发者可以更加方便地管理和操作对象的集合。这个框架的核心接口包括Collection、Set、List和Map,它们之间有着密切的关系和各自...
为了提高效率,MerginUtils可能会利用Java的集合框架特性,如迭代器和流(Stream),以及并行处理能力,以减少循环和提高并发性。例如,它可能会使用Java 8的Stream API来进行列表或映射的并行合并。 5. **使用示例*...
本文档主要讲解Java集合框架中的ArrayList、HashMap和Collections类的使用,通过一个扑克牌游戏的示例程序来演示这些类的应用。 一、 Java集合框架 Java集合框架(Java Collections Framework)是Java语言中对集合...
【Java 泛型详解】 Java 泛型是自Java SE 1.5版本引入的一种强大的编程工具,...在实际开发中,泛型能够帮助你构建更加灵活的容器类,比如集合框架中的 `ArrayList<T>`、`HashMap<K, V>` 等,它们都广泛地应用了泛型。
Java集合框架中的Map接口表示一种键值对(key-value)的数据结构,其中每个元素都包含一个唯一的键和对应的值。在Map中,每个键必须是唯一的,而值可以重复。Map接口提供了一些方法来实现基本的键值对操作,例如添加...
- Java集合框架(如ArrayList、LinkedList、HashMap等)广泛使用了泛型,确保插入和检索的对象类型与集合定义的类型一致。 - 使用泛型集合可以避免`ClassCastException`,并提高代码的可读性和安全性。 7. **野...
5. **泛型与集合**:Java集合框架广泛使用了泛型。例如,`ArrayList<T>`、`HashMap<K, V>`等都是泛型集合,它们强制我们在创建集合实例时指定类型,避免了装箱和拆箱操作,提高了效率。 6. **野指针警告**:当你...
HashMap是Java编程语言中用于存储键值对的数据结构,它属于集合框架的一部分,实现了Map接口。HashMap基于哈希表(也称为散列表)原理工作,提供了快速的插入、删除和查找操作。下面是HashMap的详细说明: HashMap...
HashMap在Java集合框架中扮演着重要角色,提供快速的查找、插入和删除操作,平均时间复杂度为O(1)。下面将详细介绍HashMap的特点、功能以及如何进行遍历。 **HashMap特点** 1. **键的唯一性**:HashMap中的键是唯一...
2. `HashMap<K, V>`:等同于C#的`Dictionary<TKey, TValue>`,用于存储键值对。 3. `LinkedList<E>`:实现了`List<E>`接口,提供链表功能。 4. `Deque<E>`:双端队列,支持在两端进行插入和删除操作,可以作为栈或...
Java 2集合框架是Java语言中用于存储和管理对象的核心组件,它提供了一套标准的接口和类,使得程序员能够高效地操作数据集合。这个框架的设计目标是提高代码的复用性和灵活性,允许开发者根据需求选择不同的数据结构...