目录
(一) 数据结构
- 列举java的集合以及集合之间的继承关系:
- 容器类介绍以及之间的区别(Java容器主要可以划分为4个部分:List列表、Set集合、Map映射、工具类(Iterator迭代器、Enumeration枚举类、Arrays和Collections))
- List,Set,Map的区别:List能插入重复对象,可插入多个Null元素;Set不允许有重复对象,能有一个Null元素,set是无序的,但 TreeSet 能进行排序;Map是一个接口,并不是collection的子接口或实现类,key最多只有一个Null值。
Map相关
- HashMap实现原理:根据关键字一次找到地址。用链地址法(数组+链表/红黑树,链表长度大于8就会转化为红黑树)解决的hash冲突。
- HashMap如何put数据(从HashMap源码角度讲解)? 扩容时导致的死循环 & 数据覆盖使得其线程不安全,HashMap 细节
- 首次put时,初始化内存;key为null时放到table[0];
- 计算hash值,根据hash值和table长度按位与计算数组下标;
- 若产生碰撞,使用链地址法解决。
- ConcurrentHashMap的实现原理:1.7之前使用分段锁机制,线程安全且高效。1.8之后使用 CAS + synchronized + Node + 红黑树 来实现,这样就将锁的粒度降低了,同时使用 synchronized 来加锁,相比于 ReentrantLock 来说,会节省比较多的内存空间。
- TreeMap具体实现:底层使用红黑树,支持自动排序。
- HashMap、HashSet、HashTable的区别:
- HashTable不允许key和value为null;
- HashTable是线程安全的,put,get方法使用synchronized,效率低下;HashMap是非synchronized的,但可通过 Collections.synchronizedMap返回同步的map;
- HashMap不保证顺序性。HashSet是封装的HashMap;
- HashSet与HashMap怎么判断集合元素重复? 先判断hashcode,若相等再比较key equals方法。HashSet基于HashMap实现,只存了key。
- LinkedHashMap 继承HashMap,内部还多了一个双向链表来维护键值对顺序,可保证插入顺序与访问顺序。遍历速度慢。
- SpareArray:Android独有的数据结构;用两个数组,用来存放key以及value值的,核心思想是通过折半查找来找到key对应的位置,然后取出值,或者插入值!时间复杂度log(n)。高效。转为移动设备定制的,在一定情况下取代HashMap。(参考:HashMap,ArrayMap,SparseArray源码分析及性能对比)
1.在数据量小的时候一般认为1000以下,key为int的时候,使用SparseArray(插入时数据迁移,会变慢)确实是一个很不错的选择,内存大概能节省30%,相比用HashMap,因为它key值不需要装箱,所以时间性能平均来看也优于HashMap!
2.ArrayMap相对于SparseArray,特点就是key值类型不受限,任何情况下都可以取代HashMap,但是通过研究和测试发现,ArrayMap的内存节省并不明显。
hash冲突
hash冲突:hashCode相同,而equals不等。
如何解决:开放地址法,链地址法,再hash法,建立一个公共溢出区。
链表
- ArrayList和LinkedList的区别,以及应用场景:ArrayList适合查找、LinkedList适合增删。
- 什么是深拷贝和浅拷贝:浅拷贝是拷贝地址,深拷贝是复制一份同样的数据。
- 手写链表逆序代码。
- 合并多个单有序链表(假设都是递增的):递归调用思路比较明确。判断当前L1,L2指向的节点值的大小.根据结果,让头指针指向小节点,并让这个节点往下走一步,作为递归函数调用的参数放入,返回的就是新的两个值的比较结果,则新的比较结果放入头结点的下一个节点.
树
- 二叉树的广度优先遍历和深度优先遍历 :广度用队列(比如ArrayDeque,使用add,remove方法。遍历一个节点后先加入其做节点,再加入其右节点),深度用栈(Stack,使用push、pop方法。遍历一个节点后先压入右节点,再压入左节点)。
- 二叉树前序、中序、后序遍历:二叉树遍历
- 红黑树:方便自平衡。
- B+树 :每个节点通常有多个孩子。 ①IO次数更少 ②查询性能很稳定 ③范围查询更简便
- 图:存在零个及以上指向上一节点(或者根节点)的引用,我们称之为图
堆
堆和树的区别:堆是一种特殊的树。
- 顺序:堆的特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。
- 内存占用:普通树占用的内存空间比它们存储的数据要多。
- 搜索:二叉树中搜索很快,但堆很慢。使用堆的目的是将最大(或者最小)的节点放在最前面,从而快速的进行相关插入、删除操作。
栈:只能栈顶进行插入删除操作。
堆和栈在内存中的区别是什么:栈存储局部变量,使用完后销毁。堆存对象,数组等,用内存回收机制销毁。
(二)算法
- 常见排序算法有哪些?
快速排序:选择出一个数做基准,把小于基准的数放在基准的前面,大于基准的数放在后面;
冒泡排序:每次比较相邻2个元素,大的移到后面,最大的优先筛选出了;(交换次数可能比较多)
选择排序:在未排序序列中找到最小元素,存放到排序序列的起始位置;
插入排序:把未排序的数按顺序插入之前已经排序的元素中;
- 最快的排序算法是哪个? 快速排序, 不稳定。
- 堆排序过程、时间复杂度及空间复杂度