JAVA面试题之容器(集合)

1.java 容器都有哪些?

容器分为两大类:Collection 和 Map;

Collection 又分为 set 和 list;

set 包含 HashSet 和 TreeSet:

  • HashSet:基于哈希表实现,有以下特点:不允许重复、允许有且只有一个null值、无序、无索引。LinkedHashSet和HashSet一样是基于哈希表实现,但是LinkedHashSet在HashSet的基础上多了一个链表,这个链表就是用来维护容器中每个元素的顺序的,所以LinkedHashSet的特点是:不允许重复、允许有且只有一个null值、有序、无索引。
  • TreeSet: TreeSet是SortedSet接口的唯一实现类,是基于二叉树实现的。TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。有以下特点:不允许重复、不允许有null值、无索引。

list 包含 ArrayList、LinkedList 和 Vector:

  • ArrayList:基于数组实现,其特点是:查询快、增删慢。查询快是因为数组的空间是连续的,查询时只要通过首地址和下标很快就能找到元素。增删慢是因为数组是不能扩容的,一旦增加或者删除元素,内部操作就是新开辟一个数组把元素copy到新的数组,老的数   组等待被垃圾回收。
  • LinkedList:基于数链表实现,其特点是:查询慢、增删快。
  • Vector:基于数组实现,相比 ArrayList 它是线程安全的。

Map是双列集合的超类,也就是键值对形式,包含 HashMap、Hashtable 和 TreeMap:

HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。

  • HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
  • HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
  • 另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
  • 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
  • HashMap不能保证随着时间的推移Map中的元素次序是不变的。
  • LinkedHashMap和hashMap的区别在于多维护了一个链表,用来存储每一个元素的顺序,就跟HashSet和LinkedHashSet差不多。
  • HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap。

2.Collection 和 Collections 有什么区别?

  • Collection是JDK中集合层次结构中的最根本的接口。定义了集合类的基本方法。
  • Collections是一个包装类。它包含有各种有关集合操作的静态多态方法,不能实例化,像一个Collection集合框架中的工具类。

3.List、Set、Map 之间的区别是什么?

  • List:有序集合
  • Set:不重复集合,LinkedHashSet按照插入排序,SortedSet可排序,HashSet无序
  • Map:键值对集合

4.HashMap 和 Hashtable 有什么区别?

HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。

  • HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
  • HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
  • 另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
  • 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。

5.如何决定使用 HashMap 还是 TreeMap?

当需要得到一个有序的结果时就应该使用TreeMap(因为HashMap中元素的排列顺序是不固定的)。除此之外,由于HashMap有更好的性能,所以大多不需要排序的时候我们会使用HashMap。

6.说一下 HashMap 的实现原理?

HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存在 bucket 里。当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。当 hash 冲突的个数比较少时,使用链表否则使用红黑树。

7.说一下 HashSet 的实现原理?

HashSet是基于HashMap 实现的,HashSet 底层使用HashMap来保存所有元素,因此HashSet的实现比较简单, 相关HashSet 的操作, 基本上都是直接调用底层HashMap的相关方法来完成, HashSet不允许重复的值,并且元素是无序的。

8.ArrayList 和 LinkedList 的区别是什么?

  • ArrayList:基于数组实现,其特点是:查询快、增删慢。
  • LinkedList:基于数链表实现,其特点是:查询慢、增删快。

9.如何实现数组和 List 之间的转换?

数组转List:使用 JDK 中 java.util.Arrays 工具类的 asList 方法。

List转数组:使用 List 的toArray方法。

10.ArrayList 和 Vector 的区别是什么?

Vector 比 ArrayList 线程更安全

11.Array 和 ArrayList 有何区别?

  • Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
  • Array大小是固定的,ArrayList的大小是动态变化的。
  • ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
  • 对于基本类型数据,ArrayList 使用自动装箱来减少编码工作量;而当处理固定大小的基本数据类型的时候,这种方式相对比较慢,这时候应该使用Array。

12.在 Queue 中 poll()和 remove()有什么区别?

poll()和remove()都将移除并且返回队列的头,但是在poll()在队列为空时返回null,而remove()会抛出NoSuchElementException异常。

13.哪些集合类是线程安全的?

Vector、Hashtable

14.迭代器 Iterator 是什么?

迭代器 Iterator 是一种设计模式,它可以遍历并且可以选择序列中的一个对象;迭代器通常被称为轻量级的对象,因为创建它的代价非常小;在Java中的迭代器是非常简单的,只能用于顺序访问集合对象的元素。

15.Iterator 怎么使用?有什么特点?

使用:

  • Iterator() 要求容器返回一个Iterator。Iterator将准备好返回序列的第一个元素。
  • 使用next() 获得序列中的下一个元素
  • 使用hasNext() 检查序列中是否还有元素。
  • 使用remove() 将迭代器新近返回的元素删除。

特点:

  • Iterator遍历集合元素的过程中不允许线程对集合元素进行修改,否则会抛出ConcurrentModificationEception的异常。
  • Iterator遍历集合元素的过程中可以通过remove方法来移除集合中的元素,删除的是上一次Iterator.next()方法返回的对象。
  • Iterator必须依附于一个集合类对象而存在,Iterator本身不具有装载数据对象的功能。
  • next() 方法,该方法通过游标指向的形式返回Iterator下一个元素。

16.Iterator 和 ListIterator 有什么区别?

相同点:

  • 两种方法都可以遍历集合元素使用。
  • 都是集合中提供的内部方法。

不同点:

  • Iterator在使用过程中,不能对集合元素进行添加操作,否则会抛出异常。
  • 使用范围不同;Iterator可以在所有集合中使用,而ListIterator只能在List类型与子类型
  • listIterator有add方法,可以向集合中添加元素,而iterator不能。
  • listiterator和iterator都有hasnext和next方法可以顺序遍历元素, 但是listiterator有hasprevious和previous方法,可以逆向遍历元素
  • listiterator可以定位当前的索引位置 nextIndex和previousIndex可以实现,iterator没有此功能
  • listiterator可以实现对对象的修改set()方法可以实现,iterator仅可以遍历,不能修改。

17.怎么确保一个集合不能被修改?

  • 通过 Collections. unmodifiableCollection(Collection c)
  • 通过Arrays.asList创建的集合
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值