Java基础问题

为什么常用ArrayList,而不是LinkedList

  1. 底层数据结构数组,需要连续内存
  2. 随机访问快
  3. 尾部插入,删除性能可以,但其它部分插入删除都会移动数据,因此性能会低
  4. 利用局部性原理(CPU 缓存会读取元素及其周围的元素一次性加载到缓存中)
  5. 简单介绍ArrayList

    1. ArrayList 底层的数据结构是数组
    2. 新建一个 ArrayList 的时候初始长度是 0 ,注意这里是 0 ,只有在首次 add 方法的时候才会扩容到 10。
    3. ArrayList 在构建的时候需要一块连续的空间,这是因为底层是数组决定的。
    4. 因为 ArrayList 的底层实现是数组,所以它可以随机访问,根据数组下标可以快速的定位到一个元素,JVM 层面在决定某个 List 是否可以随机访问时,是检查有没有实现 RandomAccess 接口,这个接口是一个空接口,就是为了标识那些底层实现是数组的集合。
    5. add 方法扩容(确认一下版本??? ):java int newCapacity = oldCapacity + (oldCapacity >> 1); 也不是完完全全的 1.5 倍
    6. addAll 方式的扩容,下次扩容的容量和需要的容量对比,选择大的作为扩容后的容量。
    7. 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。

        1. private class Itr implements Iterator<E> {
        2. int cursor; // index of next element to return
        3. int lastRet = -1; // index of last element returned; -1 if no such
        4. int expectedModCount = modCount;
        5. ...
        6. ...
        7. ...
        8. final void checkForComodification() {
        9. if (modCount != expectedModCount)
        10. throw new ConcurrentModificationException();
        11. }
      • 多说一句,对应的 CopyOnWriteArrayList 就是 fail-safe 的,为什么是 safe 就是因为它内部的迭代器没有做相关的检查。为的就是读写分离,读的时候还可以写入。

  6. LinkedList 介绍
    1. LinkedList 的底层实现是链表
    2. LinkedList插入头尾快,如果插入的元素在中间,还是要先从头开始找到中间的位置,找到中间的位置本身就是一个耗时动作。
    3. LinkedList 因为底层是链表,所有需要的空间可以是不连续的
    4. 同样的元素下占用的空间要比 ArrayList 大,因为要维护前后索引。
    5. LinkeList 也是 fail-fast 实现。
  7. 局部性原理
    1. CPU 缓存会读取元素及其周围的元素一次性加载到缓存中。
    2. 内存读取的单位在几百纳秒,而 CPU 的读取在几纳秒,CPU 缓存的读取在十几纳秒到几十纳秒之间。

      Java8流处理

      Collectors 的方法

      https://www.cnblogs.com/felordcn/p/collectors.html
      特别对于 Java 8 Stream Api 来说非常有用。它提供了collect() 方法来对 Stream 流进行终结操作派生出基于各种策略的结果集。
  • 底层使用迭代器

    类型归纳

    1. Collectors.toList();
    2. Collectors.toMap();
    3. Collectors.toSet();
    4. Collectors.toCollection();
    5. Collectors.toConcurrentMap();

    joining

    将元素以某种规则连接起来。
    1. Collectors.joining();
    2. Collectors.joining(CharSequence delimiter);
    3. Collectors.joining(CharSequence delimiter,CharSequence prefix,CharSequence suffix)
    用的比较多的是读取 HttpServletRequest 中的 body
    1. HttpServletRequest.getReader().lines().collect(Collectors.joining());

    collectingAndThen

    groupingBy

    partitioningBy

    counting

    maxBy/minBy

    summingInt/Double/Long

    summarizingInt/Double/Long

    mapping

    reducing

    fastjson基本问题

  1. 使用JSON.parseObject方法将json转化为对象时,对象之间可以多层嵌套,也可以循环嵌套。对象也可以继承其他对象

    1. T t=JSON.parseObject(json.toString(),T.class);
    • springboot API接口调用返回基本上都可以视为json结构
    • 注意:对象的setter和getter方法要齐全,少一个则对应的内容会提取不到。
  2. aaa