Java基础问题
为什么常用ArrayList,而不是LinkedList
- 底层数据结构数组,需要连续内存
- 随机访问快
- 尾部插入,删除性能可以,但其它部分插入删除都会移动数据,因此性能会低
- 利用局部性原理(CPU 缓存会读取元素及其周围的元素一次性加载到缓存中)
简单介绍ArrayList
- ArrayList 底层的数据结构是数组
- 新建一个 ArrayList 的时候初始长度是 0 ,注意这里是 0 ,只有在首次 add 方法的时候才会扩容到 10。
- ArrayList 在构建的时候需要一块连续的空间,这是因为底层是数组决定的。
- 因为 ArrayList 的底层实现是数组,所以它可以随机访问,根据数组下标可以快速的定位到一个元素,JVM 层面在决定某个 List 是否可以随机访问时,是检查有没有实现 RandomAccess 接口,这个接口是一个空接口,就是为了标识那些底层实现是数组的集合。
- add 方法扩容(确认一下版本??? ):
java int newCapacity = oldCapacity + (oldCapacity >> 1);
也不是完完全全的 1.5 倍 - addAll 方式的扩容,下次扩容的容量和需要的容量对比,选择大的作为扩容后的容量。
Iterator 的 fail-fast(快速失效) 和 fail-safe:fail-fast 简单来说就是不允许一边遍历一边修改,而 fail-safe 允许遍历的时候修改 list, 最新的修改不会被遍历到。
fail-fast 的实现原理:主要的实现是由 Iterator 这个接口的实现类来决定的(迭代器遍历,此时是不能修改的),核心就是两个参数,一个是 ArrayList 的成员变量 modCount 这个值会在每次修改 list 的时候加 1 , 而在 ArrayList 中的 Iterator 实现类中也维护了一个变量 expectedModCount,这个值默认等于 modCount 我们使用迭代器 next 方法的时候都会比较 modCount, expectedModCount 是否相等,如果不相等就会报错,这也就保证了 fail-fast。
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
...
...
...
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
多说一句,对应的 CopyOnWriteArrayList 就是 fail-safe 的,为什么是 safe 就是因为它内部的迭代器没有做相关的检查。为的就是读写分离,读的时候还可以写入。
- LinkedList 介绍
- LinkedList 的底层实现是链表
- LinkedList插入头尾快,如果插入的元素在中间,还是要先从头开始找到中间的位置,找到中间的位置本身就是一个耗时动作。
- LinkedList 因为底层是链表,所有需要的空间可以是不连续的
- 同样的元素下占用的空间要比 ArrayList 大,因为要维护前后索引。
- LinkeList 也是 fail-fast 实现。
- 局部性原理
- CPU 缓存会读取元素及其周围的元素一次性加载到缓存中。
- 内存读取的单位在几百纳秒,而 CPU 的读取在几纳秒,CPU 缓存的读取在十几纳秒到几十纳秒之间。
Java8流处理
Collectors 的方法
https://www.cnblogs.com/felordcn/p/collectors.html
特别对于 Java 8 Stream Api 来说非常有用。它提供了collect() 方法来对 Stream 流进行终结操作派生出基于各种策略的结果集。
- 底层使用迭代器
类型归纳
Collectors.toList();
Collectors.toMap();
Collectors.toSet();
Collectors.toCollection();
Collectors.toConcurrentMap();
joining
将元素以某种规则连接起来。
用的比较多的是读取 HttpServletRequest 中的 body :Collectors.joining();
Collectors.joining(CharSequence delimiter);
Collectors.joining(CharSequence delimiter,CharSequence prefix,CharSequence suffix)
HttpServletRequest.getReader().lines().collect(Collectors.joining());
collectingAndThen
groupingBy
partitioningBy
counting
maxBy/minBy
summingInt/Double/Long
summarizingInt/Double/Long
mapping
reducing
fastjson基本问题
使用JSON.parseObject方法将json转化为对象时,对象之间可以多层嵌套,也可以循环嵌套。对象也可以继承其他对象
T t=JSON.parseObject(json.toString(),T.class);
- springboot API接口调用返回基本上都可以视为json结构
- 注意:对象的setter和getter方法要齐全,少一个则对应的内容会提取不到。
- aaa