转载Java面试题笔记(一)

转载Java面试题笔记(一)

面试题及答案来源公众号Java3y,原文章地址https://segmentfault.com/a/1190000014403696,侵权联系删除。

集合

1.ArrayList和Vector的区别

相同点:都实现了List接口,都是有序的集合,底层都是数组,允许元素重复和null。
不同点:
同步性:Arraylist是非同步的,Vector是同步的,Vector更安全些但效率低,所以用Arraylist比较多,多线程的时候使用collection类加锁就好了。
存储:Vector增长了原来的一倍,而Arraylist只有0.5倍。

2.HashMap和Hashtable的区别

相同点:从存储结构和实现来讲基本上都是相同的,存储架构都是数组+链表,都实现Map接口。
不同点:
同步性:HashMap是非同步的,Hashtable是同步的,需要同步的时候使用ConcurrentHashMap。
是否允许为null:HashMap允许为null,Hashtable不允许为null。
contains方法:Hashtable有contains方法。HashMap把Hashtable的contains方法去掉了,改成了containsValue和containsKey。
继承不同:HashMap<K,V> extends AbstractMap<K,V>。Hashtable<K,V> extends Dictionary<K,V>

3.List和Map的区别

相同点:都是Java的容器,接口。
不同点:
存储结构不同:List存储的是单列的集合,Map存储的是key-value的键值对的集合。
元素是否重复:List允许重复,Map中的key值不允许重复。
是否有序:List是有序集合,Map是无序的。

4.Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()?

"""
以HashSet为例,HashSet里的元素不能重复,在源码(HashMap)是这样体现的:
// 1. 如果key 相等
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
// 2. 修改对应的value
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
"""
set集合大都使用Map的put方法来添加元素。当添加相同元素时,时根本没有插入,而是修改了value值,所以==和equals都可以。

5.Collection和Collections的区别

Collection是集合的上级接口,继承它的有Set和List接口。
Collections是集合的工具类,提供了一系列的静态方法对集合的搜索、查找、同步等操作。

6.说出ArrayList,LinkedList的存储性能和特性

特性:ArrayList的底层是数组,LinkedList的底层是双向链表。
存储性能:
1.ArrayList它支持以角标位置进行索引出对应的元素(随机访问),而LinkedList则需要遍历整个链表来获取对应的元素。因此一般来说ArrayList的访问速度是要比LinkedList要快的
2.ArrayList由于是数组,对于删除和修改而言消耗是比较大(复制和移动数组实现),LinkedList是双向链表删除和修改只需要修改对应的指针即可,消耗是很小的。因此一般来说LinkedList的增删速度是要比ArrayList要快的
双向链表:是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

7.Enumeration和Iterator接口的区别

Iterator替代了Enumeration,Enumeration是一个旧的迭代器了。与Enumeration相比,Iterator更加安全,因为当一个集合正在被遍历的时候,它会阻止其它线程去修改集合

8.ListIterator有什么特点

ListIterator继承了Iterator接口,它用于遍历List集合的元素
ListIterator可以实现双向遍历,添加元素,设置元素

9.并发集合类是什么?

Java1.5并发包(java.util.concurrent)包含线程安全集合类,允许在迭代时修改集合。迭代器被设计为fail-fast的,会抛出ConcurrentModificationException。
一部分类为:CopyOnWriteArrayList,ConcurrentHashMap,CopyOnWriteArraySet。

10.Java中HashMap的key值要是为类对象则该类需要满足什么条件?

需要同时重写该类的hashCode()方法和它的equals()方法。
从源码可以得知,在插入元素的时候是先算出该对象的hashCode。如果hashcode相等话的。那么表明该对象是存储在同一个位置上的。如果调用equals()方法,两个key相同,则替换元素。如果调用equals()方法,两个key不相同,则说明该hashCode仅仅是碰巧相同,此时是散列冲突,将新增的元素放在桶子上。一般来说,我们会认为:只要两个对象的成员变量的值是相等的,那么我们就认为这两个对象是相等的!因为,Object底层比较的是两个对象的地址,而对我们开发来说这样的意义并不大~这也就为什么我们要重写equals()方法。重写了equals()方法,就要重写hashCode()的方法。因为equals()认定了这两个对象相同,而同一个对象调用hashCode()方法时,是应该返回相同的值的!
总结:equals方法比较的是内容,当时键值对只要key不一样,那就是不一样的,所以要改写equals方法。同样不同的对象需要返回不一样的hashcode所以hashcode方法也需要改写。

11.ArrayList集合加入1万条数据,应该怎么提高效率

ArrayList的默认初始容量为10,要插入大量数据的时候需要不断扩容,而扩容是非常影响性能的。因此,现在明确了10万条数据了,我们可以直接在初始化的时候就设置ArrayList的容量!这样就可以提高效率了。

12.与Java集合框架相关的有哪些最好的实践

  1. 根据需要确定集合的类型。如果是单列的集合,我们考虑用Collection下的子接口ArrayList和Set。如果是映射,我们就考虑使用Map~
  2. 确定完我们的集合类型,我们接下来确定使用该集合类型下的哪个子类~我认为可以简单分成几个步骤:
    • 是否需要同步
      • 去找线程安全的集合类使用
    • 迭代时是否需要有序(插入顺序有序)
      • 去找Linked双向列表结构的
    • 是否需要排序(自然顺序或者手动排序)
      • 去找Tree红黑树类型的(JDK1.8)
  3. 估算存放集合的数据量有多大,无论是List还是Map,它们实现动态增长,都是有性能消耗的。在初始集合的时候给出一个合理的容量会减少动态增长时的消耗~
  4. 使用泛型,避免在运行时出现ClassCastException
  5. 尽可能使用Collections工具类,或者获取只读、同步或空的集合,而非编写自己的实现。它将会提供代码重用性,它有着更好的稳定性和可维护性
原文地址:https://www.cnblogs.com/hjss/p/13447027.html