Android面试刨根问底之常用源码篇(一),kotlin协程和线程的区别

本文探讨了Android面试中常问的HashMap相关问题,包括其内部实现、扩容机制以及与Kotlin协程的区别。HashMap使用数组+链表的数据结构,当元素超过一定数量时会进行扩容,容量始终为2的幂次。Kotlin协程提供了一种轻量级的线程管理方式,与多线程不同,适用于非阻塞I/O操作。文章还介绍了hashing概念、HashMap中的碰撞解决策略以及equals()和hashCode()的重要性,并讨论了SparseArray和ArrayMap在特定场景下替代HashMap的选择。最后,文章分析了Message、Handler、MessageQueue和Looper的工作原理,揭示了Android消息处理机制的细节。
摘要由CSDN通过智能技术生成

// (The javadoc description is true upon serialization.

// Additionally, if the table array has not been allocated, this

// field holds the initial array capacity, or zero signifying

// DEFAULT_INITIAL_CAPACITY.)

int threshold;

public V put(K key, V value) {

return putVal(hash(key), key, value, false, true);

}

//实际存储方法

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {}

//扩容方法

final Node<K,V>[] resize() {}

public V get(Object key) {

Node<K,V> e;

return (e = getNode(hash(key), key)) == null ? null : e.value;

}

//实际取值方法

final Node<K,V> getNode(int hash, Object key) {}

  • 用法
  1. put(key,value)

调用hashCode(key),使用node存储hash,key,value,如果hashcode存在则使用链表存储。

  1. get(key)

根据key的hashcode找到Entry,然后获取值对象,如果根据hashcode找到的是个链表,再去根据key.equals()判断,链表中正确的节点。

  • 关于扩容

当HashMap的大小超过了阈值(size> threshold)的时候(默认的装填因子为0.75,也就是说当一个map填满了它定义容量的75%就会去扩容),HashMap大小会扩大到原来的2倍。整个过程类似于创建新的数组,将原数组的元素重新hash后放到新数组中(rehashing)。

HashMap是非同步的,所以在多线程中使用时需要注意扩容等问题

  • 相关概念

  • hashing的概念

  • HashMap中解决碰撞的方法

  • equals()和hashCode()的应用,以及它们在HashMap中的重要性

  • 不可变对象的好处

  • HashMap多线程的条件竞争

  • 重新调整HashMap的大小

参考地址:http://www.importnew.com/7099.html

以上是网上能搜到的解释,下面是个人总结的知识点提要

如面试遇到此问题,第一步,反问面试官,您说的是哪个版本的HashMap

  • hashmap底层使用 数组+链表 的数据结构,实现存储数据,使用拉链法解决碰撞问题。

  • map.put(key,value)的时候,内部会对key进行一次hash算法,得到一个hash值,对这个hash值&操作得到元素在数组中的位置。

  • 如果该位置没有元素,那么直接加入,如果发生碰撞了,那么用拉链法,需要遍历链表比较key和hash值,如果有就覆盖,没有就到表尾了,所以会插到表尾。

  • 初始容量为16,加载因子0.75,当map添加的元素超过12个的时候会触发扩容机制。数组的容量翻倍,已经存入的元素做rehash的操作,重新在数组中找位置存储。

  • java8后改为碰撞链表元素超过8个,用红黑树实现

  • java8在表尾,java7是在链表头插入

思考点:

什么情况下考虑使用SparseArray和ArrayMap替换HashMap的情况


相关面试题

1. 为什么HashMap的容量总是2x?

从源码中可以看到,当putVal方法中,是通过tab[i = (n - 1) & hash]得到在数组中位置的。

依稀记得当年在学校中,学到hash算法的时候,学的都是n%size运算,来确定数值在数组中的位置,而HashMap中为什么要用到&运算呢。

原因如下

  1. 大家都知道&运算要比%运算速度快,虽然可能是几毫米的差别。

  2. 在n为2x时,(n-1)&hash == hash%n

为什么容量总是2x?

首先,Hash算法要解决的一个最大的问题,就是hash冲突,既然不能避免hash冲突,那么就要有个好的算法解决。

而在做&运算时,如果选用非2n的数时,n-1转换为二进制,不能保证后几位全为1,这样做在&hash的运算中,不能做到均匀分布。违背了(n-1)&hash的初衷。

(16)10 = 24 = (10000)2

(16-1)10 =(1111)2

假设n的值非2x值,10

(10-1)10 =(1001)2

(19-1)10
 =(10011)2

10011

&1111

=(11)2=(3)10

10011

&1001

=(1)2=(1)10

同样的%运算,19%16 = 3 ,19%10 = 9。

任意一个数与(1111)2做&运算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值