Java、Android数据结构小节
Java 数据结构
List
List 都有序; 线程不安全; 有长度; 内部持有 modCount 记录修改次数
ArrayList 默认长度为10、超出长度时进行扩容(0.5倍),最大长度 2 的 31 次方 -8, 超出会OOM; 特点: 查快删改慢
LinkedList 双向链表, 链表通过内部类 Node 对象实现; 增删快查找慢, 查询做了二分(下标前、后半部分)查询优化
List 承载的实体实现 Comparable、Comparator 接口可以让 List 实现快速排序
Collections.synchronizedList(list); 可以使 List 线程安全
new ArrayList(new String[]) 以及 List.toArray() 可以实现 List、 Array 互转
Arrays.asList() 返回的 List 是 Arrays 的内部类, 它未提供写操作, 所以是只读的
Map
Map 共有特性
无序; 线程不安全;
Hashtable
线程安全 (公开方法都加了 synchronized )
不允许 null key 和 null value
默认容量为 11, 默认负载因子 0.75
当 size > 容量 * 负载因子 时, 容量会扩容到 2N +1
该类已被淘汰(注意不是废弃), 如果不需要线程安全可以使用 HashMap 代替, 如果需要线程安全可以使使用 ConcurrentHashMap
HashMap
允许一个 null key 和多个 null value(做了额外处理)
默认容量为16, 容量 2的N次方; 默认负载因子为 0.75
手动设置的容量基本会被忽略, 设置的容量如果大于最大容量, 容量会被重设回最大容量
当 size > 容量 * 负载因子 时, 容量会扩容两倍
更多细节可以查阅 https://yikun.github.io/2015/04/01/Java-HashMap%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%8F%8A%E5%AE%9E%E7%8E%B0/ 以及 https://tech.meituan.com/2016/06/24/java-hashmap.html
Hashtable 和 HashMap 的对比
HashMap 抛弃了 Hashtable 线程安全特性并经过一系列特定设定使非线程安全场景的 Map 结构数据存取更加高效
HashMap 线程不安全; Hashtable 线程安全;
HashMap 默认容量(16) 和扩容容量都是 2的N次方; Hashtable 的默认容量(11) 和扩容容量(2N + 1). 素数的容量设计可以减小 key 的 hash碰撞问题, 但是 2的N次方 容量设计可以更高效的获取到 key 在哈希桶的位置(Entry数组位置)
HashMap 内部对 key 的 hashCode 做了一套新的 hash 运算规则, 让高位也参与位置计算, 从而减小碰撞概率.
HashMap 在发生碰撞后把节点实现改为链表, 在节点链表长度超过 7 后, 把链表改为树以增加查询效率
ConcurrentHashMap
线程安全, 多线程优化的 Map 结构实现
不允许 null key 和 null value
其他特性同 HashMap类似
LinkedHashMap
HashMap 的子类, 将结构与操作更改为链表形式, 可以保证有序性
accessOrder 默认fasle, 代表基于插入顺序; 修改为 true 后重写 removeEldestEntry 方法用来快速实现 lru 算法
TreeMap
不允许 null key 但可以 null value
可以对元素进行排序, 无序集合(插入顺序和便利顺序不一致)
Collections.synchronizedMap(map); 可以使线 Map 程安全.
Map 的 key 需要具有不可变性并且重写 equals() 和 hashCode() 方法
HashMap 和 Hashtable 的底层数据结构是一个数组, 结合了顺序表和单向链表的形式,内部的每一个节点都是 Node 对象
Set (这部分没有用心写)
线程不安全, 无序且元素不能重复
底层使用了 map 进行实现(HashMap & LinkedHashMap),借用 map 的 key 不能重复的特性, 来实现不重复性
HashSet、LinkedHashSet、TreeSet 的区别
都无法保证线程安全, 底层都使用 map 实现不重复性(所以特性也在 map 中),Set 都不能使用 get(index) 的方法获取元素, 只能使用 iterator 进行获取. 其中:
HashSet 使用 HashMap, 无法保证有序性。
LinkedHashSet 使用 LinkedHashMap, 可以保证有序性
TreeSet 使用 NavigableMap, 可以使用 Comparator 来控制顺序
Collections.synchronizedSet(set);可以使Set线程安全
Android 数据结构
SparseArray、SparseBooleanArray、SparseIntArray、SparseLongArray
内部 key、value 使用数据实现, 使用 int 作为 key, 对于 Boolean、 Int 以及 Long 的额外处理也免除了 value 的装箱行为, 提升性能
内部的数组采用了压缩方式表示稀疏数组, 节省内存
数据的存取添加了二分查找处理,加快了处理速度
添加数据时使用 append 操作性能优异, 不建议直接使用 put
适用场景为 key 可以使用 int 类型并且数据量在千级以内(二分查找的原因)
LongSparseArray
使用 long 作为 key 其他与 SparseArray 无异; 该类在 androidx.collection 包
ArrayMap
内部使用数组实现; 数据存取添加了二分查找处理
推荐在千级以下数据量情况下使用 ArrayMap 代替 HashMap
ArraySet
同 ArrayMap 是 Android 对 set 的一个实现
关于我
更多Android高级面试合集放在github上面了
需要的小伙伴可以点击关于我 联系我获取
非常希望和大家一起交流 , 共同进步
也可以扫一扫, 目前是一名程序员,不仅分享 Android开发相关知识,同时还分享技术人成长历程,包括个人总结,职场经验,面试经验等,希望能让你少走一点弯路。