Java面试题之集合

Java面试题之集合

一、ArrayList和Vextor的区别

共同点:

  • 这两个类都实现了List接口,它们都是有序的集合(存储有序),底层是数组。我们可以按位置索引号取出某个元素,允许有重复和为null.

区别:

  • 同步性:
    (1) .ArrayList是非同步的
    (2) Vector是同步的
    (3 )即使需要同步的时候,我们可以使用Collections工具类来构建出同步的ArrayList而不用Vector。
  • 扩容大小:
    (1)Vector增长原来的一倍,ArrayList增长原来的0.5倍

二、HashMap和Hashtable的区别

共同点:

  • 从存储结构和实现来讲基本上都是相同的,都是实现Map接口。

区别:

  • 同步性:
    (1) HashMap是非同步的
    (2) HashTable是同步的
    (3) 需要同步的时候,我们往往不使用,而使用ConcurrentHashMap
  • 是否允许为null:
    (1) HashMap允许为null
    (2) Hashtable不允许为null
  • Contains方法:
    (1) Hashtable有contains方法
    (2) HashMap把Hashtable的contains方法去掉了,改成了containsValue和containsKey
  • 继承不同:
    (1) HashMap extends AbstractMap
    (2) HashMap把Hashtable的contains方法去掉了,改成了containsValue和containsKey.

三、List和Map的区别

共同点:

  • 都是Java常用的容器,都是接口

不同点:

  • 存储结构不同:
    (1) List是存储单列的集合
    (2) Map存储的是key-value键值对的集合
  • 元素是否可重复:
    (1) List允许元素重复
    (2) Map不允许key重复
  • 是否有序:
    (1) List集合是有序的(存储有序)
    (2) Map集合是无序的(存储无序)

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

我们知道Set集合实际大都使用的是Map集合的put方法来添加元素。

以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;
   }

添加元素的时候,如果key(也对应的Set集合的元素)相等,那么则修改value值。而在Set集合中,value值仅仅是一个Object对象罢了(该对象对Set本身而言是无用的)。

也就是说:Set集合如果添加的元素相同时,是根本没有插入的(仅修改了一个无用的value值)!从源码(HashMap)中也看出来,==和equals()方法都有使用!


五、Collection和Collections的区别

1.Collection是集合的上级接口,继承它的有Set和List接口

2.Collections是集合的工具类,提供了一系列的静态方法对集合的搜索、查找、同步等操作


六、说出ArrayList,LinkedList的存储性能和特性

ArrayList的底层是数组,LinkedList的底层是双向链表。

  • ArrayList它支持以角标位置进行索引出对应的元素(随机访问),而LinkedList则需要遍历整个链表来获取对应的元素。因此一般来说ArrayList的访问速度是要比LinkedList要快的。
  • ArrayList由于是数组,对于删除和修改而言消耗是比较大(复制和移动数组实现),LinkedList是双向链表删除和修改只需要修改对应的指针即可,消耗是很小的。因此一般来说LinkedList的增删速度是要比ArrayList要快的。

6.1扩展:

ArrayList的增删未必就是比LinkedList要慢。

  • 如果增删都是在末尾来操作【每次调用的都是remove()和add()】,此时ArrayList就不需要移动和复制数组来进行操作了。如果数据量有百万级的时,速度是会比LinkedList要快的。(我测试过)

  • 如果删除操作的位置是在中间。由于LinkedList的消耗主要是在遍历上,ArrayList的消耗主要是在移动和复制上(底层调用的是arraycopy()方法,是native方法)。

    • LinkedList的遍历速度是要慢于ArrayList的复制移动速度的
    • 如果数据量有百万级的时,还是ArrayList要快

七、Enumeration和Iterator接口的区别

Iterator替代了Enumeration,Enumeration是一个旧的迭代器了。

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

  • 我们在做练习的时候,迭代时会不会经常出错,抛出ConcurrentModificationException异常,说我们在遍历的时候还在修改元素。
  • 这其实就是fail-fast机制~具体可参考博文:https://blog.csdn.net/panweiwei1994/article/details/77051261

区别有三点:

  • Iterator的方法名比Enumeration更科学
  • Iterator有fail-fast机制,比Enumeration更安全
  • Iterator能够删除元素,Enumeration并不能删除元素

八、ListIterator有什么特点

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

看一下源码的方法就知道了:
在这里插入图片描述


九、并发集合类是什么?

Java1.5并发包(java.util.concurrent)包含线程安全集合类,允许在迭代时修改集合。

  • 迭代器被设计为fail-fast的,会抛出ConcurrentModificationException。
  • 一部分类为:
    • CopyOnWriteArrayList
    • ConcurrentHashMap
    • CopyOnWriteArraySet

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

需要同时重写该类的hashCode()方法和它的equals()方法。

  • 从源码可以得知,在插入元素的时候是先算出该对象的hashCode。如果hashcode相等话的。那么表明该对象是存储在同一个位置上的。
  • 如果调用equals()方法,两个key相同,则替换元素
  • 如果调用equals()方法,两个key不相同,则说明该hashCode仅仅是碰巧相同,此时是散列冲突,将新增的元素放在桶子上

一般来说,我们会认为:只要两个对象的成员变量的值是相等的,那么我们就认为这两个对象是相等的!因为,Object底层比较的是两个对象的地址,而对我们开发来说这样的意义并不大~这也就为什么我们要重写equals()方法。

重写了equals()方法,就要重写hashCode()的方法。因为equals()认定了这两个对象相同,而同一个对象调用hashCode()方法时,是应该返回相同的值的!


十一、ArrayList集合加入1万条数据,应该怎么提高效率?

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


十二、JAVA中集合和数组的区别。

  • 数组即可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值。
  • 集合只能存储引用数据类型(对象)。集合也能存储基本数据类型,但是在存储的时候会自动装箱变成对象。2)数组长度是固定的,不能自动增长。 集合的长度是可变的,可以根据元素的增长而增长。

十三、list/set/map的区别。

  • List以特定索引来存取元素,可以有重复元素。
  • Set不能存放重复元素。
  • Map保存键值对映射,映射关系可以是一对一或多对一。

十四、HashSet和TreeSet和LinkedHashSet区别。

  • HashSet是由一个hash来实现的,因此,它的元素是无序的。add () , remove (), contains()方法的时间复杂度是0(1)。
  • TreeSet是由一个树形的结构来实现的,它里面的元素是有序的。因此,add(),remove(),contains()方法的时间复杂度是o(logn)。
  • LinkedHashSet集合同样是根据元素的hashCode来决定元素的存储位置,使用链表维护元素的次序,所以元素看起来像是以插入顺序保存的。LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet

十五、HashMap和Hashtable的比较。

  • ConcurrentHashMap对整个桶数组进行了分段,而HashMap则没有。
  • ConcurrentHashMap在每一个分段上都用锁进行保护,从而让锁的粒度更精细一些,并发性能更好, 而HashMap没有锁机制,不是线程安全的。

十六、HashMap 底层实现原理

  • jdk1.8之前,list+链表
  • jdk1.8之后,list+链表(当链表长度达到8时,转化为红黑树)
  • HashMap扩容因子默认0.75,会浪费1/4的空间,达到扩容因子时,会将list扩容一倍,0.75是时间与空间的一个平衡值。

十七、HashMap和LinkedHashMap的区别?

  • HashMap不保证顺序,即为无序的,具有很快的访问速度。
  • HashMap最多只允许一条记录的键为Null;LinkedHashMap允许多条记录的值为Null;HashMap不支持线程的同步。
  • LinkedHashMap可以保证HashMap集合有序。存入的顺序和取出的顺序一致。

十八、ArrayList/LinkedList /HashMap初始大小,add后是多少?

  • ArrayList 初始化大小是 10 ,扩容后的大小= 原始大小*1.5
  • linkedList 是一个双向链表,没有初始化大小,也没有扩容的机制,就是一直在前面或者后面新增就 好。
  • HashMap 初始化大小是 16 ,扩容因子默认0.75当前大小 和 当前容量 的比例超过了 扩容因子,就会扩容,扩容后大小为 一倍。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值