4万字聊聊阿里二面,能抗多少?
Posted 公众号欢少的成长之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4万字聊聊阿里二面,能抗多少?相关的知识,希望对你有一定的参考价值。
我是Leo。今天聊一下阿里二面。
友情提示:觉得长收藏的时候请点右上角,底部弹出菜单点收藏。我怕你拉不到底部
聊聊Redis面试题
目录导航
MySQL
Spring
Redis
项目方案
算法
一、Java
1.1 Java重写和重载的区别?
重载: 重载就是可以允许在类中存在多个方法名的函数,他们具有相同的名字,但具有不同的参数和不同的参数个数。也是让类以统一的方式处理不同类型数据的一种手段。
重写: 重写就是父类与子类之间的多态性,对父类的函数进行重写定义,子类既可以继承父类的函数,方法也可以在父类的基础上进行特定的修改。
1.2 Java有哪些数据结构,源码分析?
①、链表(List)
链表是一种递归的数据结构,它或者为空(null),或者是指向一个结点node的引用,该节点还有一个元素和一个指向另一条链表的引用。
这里主要分析一下ArryList。
优点:查询效率高,使用频率也很高(因为在于内存的连续性,CPU的内部缓存结构会缓存连续的内存⽚段,可以⼤幅降低读取内存的性能开销)
缺点:线程不安全,增删效率低(copy数组占用太多时间)
//无参构造ArrayList的话 会初始化空对象
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = ;
// 底层的数组对象
transient Object[] elementData;
// 默认初始化为10
private static final int DEFAULT_CAPACITY = 10;
// 默认最大值
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 无参构造方法
public ArrayList()
//无惨构造,默认参数赋给数组对象
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
// 有参构造方法
public ArrayList(int initialCapacity)
//有参构造时,会传一个大小,如果大于0 就把传入的参数作为length
if (initialCapacity > 0)
this.elementData = new Object[initialCapacity];
else if (initialCapacity == 0)
//如果等于0,就直接用自带的DEFAULTCAPACITY_EMPTY_ELEMENTDATA
this.elementData = EMPTY_ELEMENTDATA;
else
//如果这个大小小于0肯定是不允许的
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
// add方法
public boolean add(E e)
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
// add方法中的ensureCapacityInternal
private void ensureCapacityInternal(int minCapacity)
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
// add方法中ensureCapacityInternal的calculateCapacity
// 这个函数其实就是处理 当是无参构造时,他会在add函数里 做+1处理 并且与自带的大小比较,取最大的值。
// 这里就是为什么很多会说 ArrayList初始化默认长度为10的原因(添加数据后是10)
private static int calculateCapacity(Object[] elementData, int minCapacity)
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
return Math.max(DEFAULT_CAPACITY, minCapacity);
return minCapacity;
// add方法中的ensureCapacityInternal的ensureExplicitCapacity
private void ensureExplicitCapacity(int minCapacity)
//modCount就是他的修改次数同时主要处理快速失败的一个作用,官方原话是这么说的
//If an implementation does not wish to provide fail-fast iterators, this field may be ignored.
//如果一个实现不希望提供快速失败迭代器,这个字段可以被忽略。
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
// 这个函数主要处理的是一个 扩容 的一个作用。
// 扩容完之后, 开始处理数据的真实大小。通过Arrays.copyOf 函数 截取当前的 扩容后的大小 也就是15赋值给elementData 底层数组
private void grow(int minCapacity)
// 首先取整个链表 数据的长度, 比如 length = 10
int oldCapacity = elementData.length;
//10 + 5 = 15 这个 15 就是最新的链表长度
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// copy 数组,耗时主要是在这个地方
elementData = Arrays.copyOf(elementData, newCapacity);
// 这个函数其实没啥用,主要就是两极的判断, 如果小于0 抛出异常,如果大于最大值 等等
private static int hugeCapacity(int minCapacity)
//
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
// 最后处理完之后, 回到add函数的 第二行代码,把新加的数据 写入当前数组对象中
JDK1.7与1.8的区别
1.7 默认构造大小为10
1.8 默认构造大小为空数组,长度为0
//无参构造方法 1.7
public ArrayList()
this(10);
public ArrayList(int initialCapacity)
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
//无参构造方法 1.8
public ArrayList()
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = ;
增删慢的原因是
在对源码进行分析的话,如果读懂源码的话,我相信大家对 grow
比较印象深刻。这个函数内会有一个Arrays.copyOf操作。也就是拷贝数组数据。这就是慢的根本原因。
tip: 这里LinkedList 我用的不多,就不做过多介绍了。后续会展开更新的再细一些。
②、哈希表(Hash)
哈希表(HashTable) 也叫散列表,是一种可以通过关键码至 K,V直接访问的数据结构。它最大的特点就是可以快速实现查找、插入和删除。
数组的最大特点就是查找容易,插入和删除困难;而链表正好相反,查找困难,而插入和删除容易。哈希表很完美地结合了两者的优点, Java 的 HashMap 在此基础上还加入了树的优点。
上源码
final float loadFactor; //记录 hashMap 装载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f; // 0.75
static final int MAXIMUM_CAPACITY = 1 << 30; // 1073741824
static final int TREEIFY_THRESHOLD = 8; //链表长度到8,就转为红黑树
static final int UNTREEIFY_THRESHOLD = 6; // 树大小为6,就转回链表
transient Node<K,V>[] table; // 哈希桶数组
transient int modCount; //记录 hashMap 发生结构性变化的次数(注意 value 的覆盖不属于结构性变化)
int threshold; //threshold的值应等于 table.length * loadFactor, size 超过这个值时进行 resize()扩容
MQ消息丢失,消息一致性,重复消费解决方案