Java:这是一份详细&全面的HashMap 1,java框架开发面试题

public final String toString() {
return getKey() + “=” + getValue();
}

/**

  • 当向HashMap中添加元素时,即调用put(k,v)时,
  • 对已经在HashMap中k位置进行v的覆盖时,会调用此方法
  • 此处没做任何处理
    */
    void recordAccess(HashMap<K,V> m) {
    }

/**

  • 当从HashMap中删除了一个Entry时,会调用该函数
  • 此处没做任何处理
    */
    void recordRemoval(HashMap<K,V> m) {
    }

}


3. 具体使用

3.1 主要使用API(方法、函数)

V get(Object key); // 获得指定键的值
V put(K key, V value); // 添加键值对
void putAll(Map<? extends K, ? extends V> m); // 将指定Map中的键值对 复制到 此Map中
V remove(Object key); // 删除该键值对

boolean containsKey(Object key); // 判断是否存在该键的键值对;是 则返回true
boolean containsValue(Object value); // 判断是否存在该值的键值对;是 则返回true

Set keySet(); // 单独抽取key序列,将所有key生成一个Set
Collection values(); // 单独value序列,将所有value生成一个Collection

void clear(); // 清除哈希表中的所有键值对
int size(); // 返回哈希表中所有 键值对的数量 = 数组中的键值对 + 链表中的键值对
boolean isEmpty(); // 判断HashMap是否为空;size == 0时 表示为 空

3.2 使用流程

  • 在具体使用时,主要流程是:
  1. 声明1个 HashMap的对象
  2. HashMap 添加数据(成对 放入 键 - 值对)
  3. 获取 HashMap 的某个数据
  4. 获取 HashMap 的全部数据:遍历HashMap
  • 示例代码

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class HashMapTest {

public static void main(String[] args) {
/**

    1. 声明1个 HashMap的对象
      */
      Map<String, Integer> map = new HashMap<String, Integer>();

/**

    1. 向HashMap添加数据(成对 放入 键 - 值对)
      */
      map.put(“Android”, 1);
      map.put(“Java”, 2);
      map.put(“iOS”, 3);
      map.put(“数据挖掘”, 4);
      map.put(“产品经理”, 5);

/**

    1. 获取 HashMap 的某个数据
      */
      System.out.println(“key = 产品经理时的值为:” + map.get(“产品经理”));

/**

    1. 获取 HashMap 的全部数据:遍历HashMap
  • 核心思想:
  • 步骤1:获得key-value对(Entry) 或 key 或 value的Set集合
  • 步骤2:遍历上述Set集合(使用for循环 、 迭代器(Iterator)均可)
  • 方法共有3种:分别针对 key-value对(Entry) 或 key 或 value
    */

// 方法1:获得key-value的Set集合 再遍历
System.out.println(“方法1”);
// 1. 获得key-value对(Entry)的Set集合
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();

// 2. 遍历Set集合,从而获取key-value
// 2.1 通过for循环
for(Map.Entry<String, Integer> entry : entrySet){
System.out.print(entry.getKey());
System.out.println(entry.getValue());
}
System.out.println("----------");
// 2.2 通过迭代器:先获得key-value对(Entry)的Iterator,再循环遍历
Iterator iter1 = entrySet.iterator();
while (iter1.hasNext()) {
// 遍历时,需先获取entry,再分别获取key、value
Map.Entry entry = (Map.Entry) iter1.next();
System.out.print((String) entry.getKey());
System.out.println((Integer) entry.getValue());
}

// 方法2:获得key的Set集合 再遍历
System.out.println(“方法2”);

// 1. 获得key的Set集合
Set keySet = map.keySet();

// 2. 遍历Set集合,从而获取key,再获取value
// 2.1 通过for循环
for(String key : keySet){
System.out.print(key);
System.out.println(map.get(key));
}

System.out.println("----------");

// 2.2 通过迭代器:先获得key的Iterator,再循环遍历
Iterator iter2 = keySet.iterator();
String key = null;
while (iter2.hasNext()) {
key = (String)iter2.next();
System.out.print(key);
System.out.println(map.get(key));
}

// 方法3:获得value的Set集合 再遍历
System.out.println(“方法3”);

// 1. 获得value的Set集合
Collection valueSet = map.values();

// 2. 遍历Set集合,从而获取value
// 2.1 获得values 的Iterator
Iterator iter3 = valueSet.iterator();
// 2.2 通过遍历,直接获取value
while (iter3.hasNext()) {
System.out.println(iter3.next());
}

}

}

// 注:对于遍历方式,推荐使用针对 key-value对(Entry)的方式:效率高
// 原因:
// 1. 对于 遍历keySet 、valueSet,实质上 = 遍历了2次:1 = 转为 iterator 迭代器遍历、2 = 从 HashMap 中取出 key 的 value 操作(通过 key 值 hashCode 和 equals 索引)
// 2. 对于 遍历 entrySet ,实质 = 遍历了1次 = 获取存储实体Entry(存储了key 和 value )

  • 运行结果

方法1
Java2
iOS3
数据挖掘4
Android1
产品经理5

Java2
iOS3
数据挖掘4
Android1
产品经理5
方法2
Java2
iOS3
数据挖掘4
Android1
产品经理5

Java2
iOS3
数据挖掘4
Android1
产品经理5
方法3
2
3
4
1
5

下面,我们按照上述的使用过程,对一个个步骤进行源码解析


4. 基础知识:HashMap中的重要参数(变量)

  • 在进行真正的源码分析前,先讲解HashMap中的重要参数(变量)
  • HashMap中的主要参数 = 容量、加载因子、扩容阈值
  • 具体介绍如下

// 1. 容量(capacity): HashMap中数组的长度
// a. 容量范围:必须是2的幂 & <最大容量(2的30次方)
// b. 初始容量 = 哈希表创建时的容量
// 默认容量 = 16 = 1<<4 = 00001中的1向左移4位 = 10000 = 十进制的2^4=16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
// 最大容量 = 2的30次方(若传入的容量过大,将被最大值替换)
static final int MAXIMUM_CAPACITY = 1 << 30;

// 2. 加载因子(Load factor):HashMap在其容量自动增加前可达到多满的一种尺度
// a. 加载因子越大、填满的元素越多 = 空间利用率高、但冲突的机会加大、查找效率变低(因为链表变长了)
// b. 加载因子越小、填满的元素越少 = 空间利用率小、冲突的机会减小、查找效率高(链表不长)
// 实际加载因子
final float loadFactor;
// 默认加载因子 = 0.75
static final float DEFAULT_LOAD_FACTOR = 0.75f;

// 3. 扩容阈值(threshold):当哈希表的大小 ≥ 扩容阈值时,就会扩容哈希表(即扩充HashMap的容量)
// a. 扩容 = 对哈希表进行resize操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数
// b. 扩容阈值 = 容量 x 加载因子
int threshold;

// 4. 其他
// 存储数据的Entry类型 数组,长度 = 2的幂
// HashMap的实现方式 = 拉链法,Entry数组上的每个元素本质上是一个单向链表

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值