目录
五、说出ArrayList,LinkedList的存储性能和特性
六、Java中HashMap的key值要是为类对象则该类需要满足什么条件?
在知乎上看到了一个大神对Java面试的总结,觉得非常好,有很多问题都是我自己面试中遇到的,所以觉得有必要总结下,因为大神总结的非常好,所以就直接把链接放上来了,有些面试问题我没有遇到过或者觉得不是很重要我就没贴上来了,当然可能会增加一下我自己遇到的问题。这里是按照分类整理的面试题,首先讲集合啦!!!
· List集合
· ConcurrentHashMap基于JDK1.8源码剖析
Java容器可分为两大类:
着重标出的那些就是我们用得最多的容器
一、ArrayList和Vector的区别
共同点:
- 这两个类都实现了List接口,它们都是有序的集合(存储有序),底层是数组。我们可以按位置索引号取出某个元素,允许元素重复和为null。
区别:
-
同步性:
- Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。
- 即便需要同步的时候,我们可以使用Collections工具类来构建出同步的ArrayList而不用Vector
-
扩容大小:
- 当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量增长原来的一倍,而ArrayList只增加原来的0.5倍,这样,ArrayList就有利于节约内存空间。
二、HashMap和Hashtable的区别
先放一张HashMap和HashTable的类继承体系图,并列出了这两个类的可供外部调用的公开方法。
从图中可以看出,两个类的继承体系有些不同。虽然都实现了Map、Cloneable、Serializable三个接口。但是HashMap继承自抽象类AbstractMap,而HashTable继承自抽象类Dictionary。
· 继承体系不同:HashMap继承自抽象类AbstractMap,而HashTable继承自抽象类Dictionary
另外HashTable比HashMap多了两个公开方法。一个是elements,这来自于抽象类Dictionary,鉴于该类已经废弃,所以这个方法也就没什么用处了。另一个多出来的方法是contains,这个多出来的方法也没什么用,因为它跟containsValue方法功能是一样的。
· contains方法:HashMap把HashTable的contains方法去掉了,改成了containsValue和containsKey
HashMap是支持null键和null值的,而HashTable在遇到null时,会抛出NullPointerException异常。这并不是因为HashTable有什么特殊的实现层面的原因导致不能支持null键和null值,这仅仅是因为HashMap在实现时对null做了特殊处理,将null的hashCode值定为了0,从而将其存放在哈希表的第0个bucket中。
·是否允许为null:HashMap支持null键和null值,HashTable不支持null键和null值
我们说HashTable是同步的,HashMap不是,也就是说HashTable在多线程使用的情况下,不需要做额外的同步,而HashMap则不行
· 同步性:HashMap是非同步的,HashTable是同步的
三、List和Map的区别
List继承自Collection接口,而Map是个顶级接口
· 存储结构不同:List是存储单列的集合,Map存储的是Key-value键值对的集合
· 元素是否可重复:List允许元素重复,Map不允许key重复
· 是否有序:List集合是有序的(存储有序),Map集合是无序的(存储无序)
四、Collection和Collections的区别
· Collection是集合的上级接口,继承它的有Set和List接口
· Collections是集合的工具类,提供了一系列的静态方法对集合的搜索、查找、同步等操作
五、说出ArrayList,LinkedList的存储性能和特性
ArrayList的底层是数组,LinkedList的底层是双向链表。
- ArrayList它支持以角标位置进行索引出对应的元素(随机访问),而LinkedList则需要遍历整个链表来获取对应的元素。因此一般来说ArrayList的访问速度是要比LinkedList要快的
- ArrayList由于是数组,对于删除和修改而言消耗是比较大(复制和移动数组实现),LinkedList是双向链表删除和修改只需要修改对应的指针即可,消耗是很小的。因此一般来说LinkedList的增删速度是要比ArrayList要快的
扩展:
ArrayList的增删未必就是比LinkedList要慢。
- 如果增删都是在末尾来操作【每次调用的都是remove()和add()】,此时ArrayList就不需要移动和复制数组来进行操作了。如果数据量有百万级的时,速度是会比LinkedList要快的。
-
如果删除操作的位置是在中间。由于LinkedList的消耗主要是在遍历上,ArrayList的消耗主要是在移动和复制上(底层调用的是arraycopy()方法,是native方法)。
- LinkedList的遍历速度是要慢于ArrayList的复制移动速度的
- 如果数据量有百万级的时,还是ArrayList要快。
六、Java中HashMap的key值要是为类对象则该类需要满足什么条件?
需要同时重写该类的hashCode()方法和它的equals()方法。
- 从源码可以得知,在插入元素的时候是先算出该对象的hashCode。如果hashcode相等话的。那么表明该对象是存储在同一个位置上的。
- 如果调用equals()方法,两个key相同,则替换元素
- 如果调用equals()方法,两个key不相同,则说明该hashCode仅仅是碰巧相同,此时是散列冲突,将新增的元素放在桶子上
一般来说,我们会认为:只要两个对象的成员变量的值是相等的,那么我们就认为这两个对象是相等的!因为,Object底层比较的是两个对象的地址,而对我们开发来说这样的意义并不大~这也就为什么我们要重写equals()
方法
重写了equals()方法,就要重写hashCode()的方法。因为equals()认定了这两个对象相同,而同一个对象调用hashCode()方法时,是应该返回相同的值的!
七、ArrayList集合加入1万条数据,应该怎么提高效率
ArrayList的默认初始容量为10,要插入大量数据的时候需要不断扩容,而扩容是非常影响性能的。因此,现在明确了10万条数据了,我们可以直接在初始化的时候就设置ArrayList的容量!
这样就可以提高效率了~
八、List去重(我遇到的面试题)
https://blog.csdn.net/Trainer2107/article/details/78571619
九、与Java集合框架相关的有哪些最好的实践?
(1)根据需要选择正确的集合类型。比如,如果指定了大小,我们会选用Array而非ArrayList。如果我们想根据插入顺序遍历一个Map,我们需要使用TreeMap。如果我们不想重复,我们应该使用Set。
(2)一些集合类允许指定初始容量,所以如果我们能够估计到存储元素的数量,我们可以使用它,就避免了重新哈希或大小调整。
(3)基于接口编程,而非基于实现编程,它允许我们后来轻易地改变实现。
(4)总是使用类型安全的泛型,避免在运行时出现ClassCastException。
(5)使用JDK提供的不可变类作为Map的key,可以避免自己实现hashCode()和equals()。
(6)尽可能使用Collections工具类,或者获取只读、同步或空的集合,而非编写自己的实现。它将会提供代码重用性,它有着更好的稳定性和可维护性
总结: