面试常温
ArrayIndexOutOfBoundsException : 数组下标越界异常!
StringBuilder与StringBuffffer的区别,StringBuilder与String的区别。
1)StringBuilder效率高,线程不安全,StringBuffffer效率低,线程安全。
2)String是不可变字符串,StringBuilder是可变字符串。为什么有这样的差异,可以深入源码去解析,
比如String类内的 priver fifinal char value[] 等方法的原因。
3)如果是简单的声明一个字符串没有后续过多的操作,使用String,StringBuilder均可,若后续对字符穿
做频繁的添加,删除操作,或者是在循环当中动态的改变字符穿的长度应该用StringBuilder。使用String
会产生多余的字符串,占用内存空间。
Collection 接口存储一组不唯一,无序的对象
List 接口存储一组不唯一,有序的对象。
Set 接口存储一组唯一,无序的对象
Map 接口存储一组键值对象,提供key到value的映射
ArrayList实现了长度可变的数组,在内存中分配连续的空间。遍历元素和随机访问元素的效率比较
高
ArrayList总结
1)arrayList可以存放null。
2)arrayList本质上就是一个elementData数组。
3)arrayList区别于数组的地方在于能够自动扩展大小,其中关键的方法就是gorw()方法。
4)arrayList中removeAll(collection c)和clear()的区别就是removeAll可以删除批量指定的元素,而
clear是全是删除集合中的元素。
5)arrayList由于本质是数组,所以它在数据的查询方面会很快,而在插入删除这些方面,性能下降很
多,有移动很多数据才能达到应有的效果
6)arrayList实现了RandomAccess,所以在遍历它的时候推荐使用for循环。
list
【arrayList和LinkedList区别】
arrayList底层是用数组实现的顺序表,是随机存取类型,可自动扩增,并且在初始化时,数组的长
度是0,只有在增加元素时,长度才会增加。默认是10,不能无限扩增,有上限,在查询操作的时候性
能更好
LinkedList底层是用链表来实现的,是一个双向链表,注意这里不是双向循环链表,顺序存取类型。
在源码中,似乎没有元素个数的限制。应该能无限增加下去,直到内存满了在进行删除,增加操作时性
能更好。
两个都是线程不安全的,在iterator时,会发生fail-fast:快速失效。
【arrayList和Vector的区别】
arrayList线程不安全,在用iterator,会发生fail-fast
Vector线程安全,因为在方法前加了Synchronized关键字。也会发生fail-fast
【fail-fast和fail-safe区别和什么情况下会发生】
简单的来说:在java.util下的集合都是发生fail-fast,而在java.util.concurrent下的发生的都是fail
safe。
1)fail-fast
快速失败,例如在arrayList中使用迭代器遍历时,有另外的线程对arrayList的存储数组进行了改变,比
如add、delete、等使之发生了结构上的改变,所以Iterator就会快速报一个
java.util.ConcurrentModifificationException 异常(并发修改异常),这就是快速失败。
2)fail-safe
安全失败,在java.util.concurrent下的类,都是线程安全的类,他们在迭代的过程中,如果有线程进行
结构的改变,不会报异常,而是正常遍历,这就是安全失败。
3)为什么在java.util.concurrent包下对集合有结构的改变,却不会报异常?
在concurrent下的集合类增加元素的时候使用Arrays.copyOf()来拷贝副本,在副本上增加元素,如果有
其他线程在此改变了集合的结构,那也是在副本上的改变,而不是影响到原集合,迭代器还是照常遍
历,遍历完之后,改变原引用指向副本,所以总的一句话就是如果在此包下的类进行增加删除,就会出
现一个副本。所以能防止fail-fast,这种机制并不会出错,所以我们叫这种现象为fail-safe。
4)vector也是线程安全的,为什么是fail-fast呢?
这里搞清楚一个问题,并不是说线程安全的集合就不会报fail-fast,而是报fail-safe,你得搞清楚前面所
说答案的原理,出现fail-safe是因为他们在实现增删的底层机制不一样,就像上面说的,会有一个副
本,而像arrayList、linekdList、verctor等,他们底层就是对着真正的引用进行操作,所以才会发生异
常。
5)既然是线程安全的,为什么在迭代的时候,还会有别的线程来改变其集合的结构呢(也就是对其
删除和增加等操作)?
首先,我们迭代的时候,根本就没用到集合中的删除、增加,查询的操作,就拿vector来说,我们都没
有用那些加锁的方法,也就是方法锁放在那没人拿,在迭代的过程中,有人拿了那把锁,我们也没有办
法,因为那把锁就放在那边