网上收集的12道典型集合面试题,看看就好。
1.ArrayList 和 Vector 的区别
都是List接口
- ArrayList 底层是数组,线程不安全,ArrayList可以替代Vector,查询速度快。
- Vector 底层也是数组,但是线程安全的,源码中有很多的synchronized可以看出,查询速度很慢。
2.HashMap 和 Hashtable 的区别
都是Map接口
- Hashtable底层是哈希散列数据结构,线程同步,不可以存储null值。HashTable是继承自Dictionary类。(Dictionary类是一个已经被废弃的类)。所有 Hashtable基本上不用了
- HashMap底层是哈希表数据,线程不同步,但是Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行。HashMap是继承自AbstractMap类
3.List 和 Map 的区别
Set和List都继承自Collection,而Map则和Collection没什么关系。
- List接口继承自Collection。List可以存储重复的元素。主要有两种实现:ArrayList和LinkedList。
- Map(映射)是一个存储键值对的容器接口。每一个元素包含一个key对象和value对象,且元素不允许重复。接口的实现主要有HashMap,LinkHashMap,TreeMap
4.Set 里的元素不能重复的,用什么方法来区分重复。
- 对于ArrayList 集合,判断元素是否重复,用equals方法
- 对于Set集合,则根据hashCode 和 equals方法来区分重复。
5.Collection 和 Collections 的区别
- Collection是集合类的上级接口,继承与他有关的接口主要有List和Set
- Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全等操作
6.说出ArrayList,LinkedList 的存储性能和特性
- ArrayList 底层是数组,线程不同步,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢。
- LinkList 底层是双向链表,线程不同步,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
7.Enumertation 和 Iterator 接口的区别
- Enumeration 接口的作用与 Iterator 接口类似,但只提供了遍历 Vector 和 Hashtable
类型集合元素的功能,不支持元素的移除操作。
for (Enumeration<E> e = v.elements();e.hasMoreElements();)
System.out.println(e.nextElement());
Iterator 接口添加了一个可选的移除操作,并使用较短的方法名。新的实现应该优先考虑使用 Iterator 接口而不是
Enumeration 接口。区别:Enumeration速度是Iterator的2倍,同时占用更少的内存。但是,Iterator远远比Enumeration安全,因为其他线程不能够修改正在被iterator遍历的集合里面的对象。同时,Iterator允许调用者删除底层集合里面的元素,这对Enumeration来说是不可能的。
Iterator 接口的用法:
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
8.ListItertator有什么特点
- 允许我们向前、向后两个方向遍历 List;
- 在遍历时修改 List 的元素;
遍历时获取迭代器当前游标所在位置。
有以下方法:
void hasPrevious()
判断游标前面是否有元素;Object previous()
返回游标前面的元素,同时游标前移一位。游标前没有元素就报
java.util.NoSuchElementException 的错,所以使用前最好判断一下;int nextIndex()
返回游标后边元素的索引位置,初始为 0 ;遍历 N 个元素结束时为 N;int previousIndex()
返回游标前面元素的位置,初始时为 -1,同时报
java.util.NoSuchElementException 错;void add(E)
在游标 前面 插入一个元素 注意,是前面void set(E)
更新迭代器最后一次操作的元素为 E,也就是更新最后一次调用 next() 或者 previous()
返回的元素。 注意,当没有迭代,也就是没有调用 next() 或者 previous() 直接调用 set 时会报
java.lang.IllegalStateException 错;void remove()
删除迭代器最后一次操作的元素,注意事项和 set 一样。
9.并发集合类是什么?
Java提供了你可以在你的并发程序中使用的,而且不会有任何问题或不一致的数据集合。基本上,Java提供两种在并发应用程序中使用的集合:
阻塞集合:这种集合包括添加和删除数据的操作。如果操作不能立即进行,是因为集合已满或者为空,该程序将被阻塞,直到操作可以进行。
非阻塞集合:这种集合也包括添加和删除数据的操作。如果操作不能立即进行,这个操作将返回null值或抛出异常,但该线程将不会阻塞。
非阻塞式列表对应的实现类:ConcurrentLinkedDeque
阻塞式列表对应的实现类:LinkedBlockingDeque
用于数据生成或者消费的阻塞式列表对应的实现类:LinkedTransferQueue
按优先级排序列表元素的阻塞式列表对应的实现类:PriorityBlockingQueue
带有延迟列表元素的阻塞式列表对应的实现类:DelayQueue
非阻塞式列表可遍历映射对应的饿实现类:ConcurrentSkipListMap
随机数字对应的实现类:ThreadLockRandom
原子变量对应的实现类:AtomicLong和AtomicIntegerArray
参考:https://blog.csdn.net/paincupid/article/details/52017292
10.Java中HashMap的Key值要是为类对象,则需要满足什么条件?
重写对象key的equals和HashCode的方法
原因:HashMap在根据key获得相应的value的时候,用的hash值和equals来判断是否是同一个key
11.ArrayList集合加入1W条数据,应该怎么提高效率
12.与Java集合框架相关的有哪些最好的实践。
- 1.假如元素的大小是固定的,而且能事先知道,我们就应该用Array而不是ArrayList。
- 2.有些集合类允许指定初始容量。因此,如果我们能估计出存储的元素的数目,我们可以设置初始容量来避免重新计算hash值或者是扩容。
3.为了类型安全,可读性和健壮性的原因总是要使用泛型。同时,使用泛型还可以避免运行时的ClassCastException。
4.使用JDK提供的不变类(immutable class)作为Map的键可以避免为我们自己的类实现hashCode()和equals()方法。
- 5.编程的时候接口优于实现。
- 6.底层的集合实际上是空的情况下,返回长度是0的集合或者是数组,不要返回null。