Java基础7:集合类常见面试题

来源:互联网 发布:iphone4移动数据开关 编辑:程序博客网 时间:2024/06/05 08:12

一.Array和ArrayList有何区别?

Array可以容纳基本类型和对象,而ArrayList只能容纳对象

Array是指定大小的,而ArrayList大小是固定的


二.ArrayListLinkedList的区别是什么?

1、ArrayList是基于数组实现,LinkedList是基于链表实现

2、ArrayList在查找时速度快,LinkedList在插入与删除时更具优势


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

常识:线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行 访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染;线程不安全就是不提供数据访问保护,多线程先后更改数据会产生数据不一致或者数据污染的情况。

一般使用synchronized关键字加锁同步控制,来解决线程不安全问题。


  • ArrayList线程不安全,Vector线程安全;
  • HashMap线程不安全,HashTable线程安全;
  • StringBuilder线程不安全,StringBuffer线程安全
  • Stack也是线程安全的,继承于Vector
  • ConcurrentHashMap是一种高效但是线程安全的集合。

四、线程安全和速度之间的取舍?

线程安全必须要使用synchronized关键字来同步控制,所以会导致性能的降低

当不需要线程安全时,可以选择ArrayList,避免方法同步产生的开销;多个线程操作同一个对象时,可以选择线程安全的Vector;

、List、Set和Map的区别和联系?

1、List和Set继承自Collection接口,而Map不是。Map是一组key-value映射的集合。

2、List特点:元素有放入顺序,元素可重复 
Map特点:元素按键值对存储,无放入顺序 
Set特点:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的) 


参考资料:list、set和map 的区别


六.HashMap的底层结构/工作原理是什么?

HashMap内部是通过一个数组实现的,只是这个数组比较特殊,数组里存储的元素是一个Entry实体(jdk8为Node),这个Entry实体主要包含key、value以及一个指向自身的next指针。HashMap是基于hashing实现的,当我们进行put操作时,根据传递的key值得到它的hashcode,然后再用这个hashcode与数组的长度进行模运算,得到一个int值,就是Entry要存储在数组的位置(下标);当通过get方法获取指定key的值时,会根据这个key算出它的hash值(数组下标),根据这个hash值获取数组下标对应的Entry,然后判断Entry里的key,hash值或者通过equals()比较是否与要查找的相同,如果相同,返回value,否则的话,遍历该链表(有可能就只有一个Entry,此时直接返回null),直到找到为止,否则返回null。
HashMap之所以在每个数组元素存储的是一个链表,是为了解决hash冲突问题,当两个对象的hash值相等时,那么一个位置肯定是放不下两个值的,于是hashmap采用链表来解决这种冲突,hash值相等的两个元素会形成一个链表。

七、HashMap和Hashtable的区别?

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

1、HashMap的key和value都允许为null,而Hashtable的key和value都不允许为null。HashMap遇到key为null的时候,调用putForNullKey方法进行处理,而对value没有处理;Hashtable遇到null,直接返回NullPointerException。

2、HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。

3、HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。

由于Hashtable是synchronized即线程安全的,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。

*:Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

八.哪些集合类提供对元素的随机访问?


ArrayList、HashMap、TreeMap和HashTable类提供对元素的随机访问。


九.遍历一个List有哪些不同的方式?

    List<String> strList = new ArrayList<>();    //for-each    for(String str:strList) {        System.out.print(str);    }    //use iterator 尽量使用这种 更安全(fail-fast)    Iterator<String> it = strList.iterator();    while(it.hasNext) {        System.out.printf(it.next());    }

十、为什么集合接口Set、List、Map没有实现Cloneable和Serializable接口?

克隆(cloning)或者序列化(serialization)的含义是跟具体的实现相关的。因此,应该由集合接口的具体实现类来决定如何被克隆或者是序列化。仅仅是接口不实现,留给具体实现类实现

实现Serializable序列化的作用:
  1. 将对象的状态保存在存储媒体中以便可以在以后重写创建出完全相同的副本;
  2. 按值将对象从一个从一个应用程序域发向另一个应用程序域。
实现 Serializable接口的作用就是可以把对象存到字节流,然后可以恢复。所以你想如果你的对象没有序列化,怎么才能进行网络传输呢?要网络传输就得转为字节流,所以在分布式应用中,你就得实现序列化。如果你不需要分布式应用,那就没必要实现实现序列化。


十一、hashCode()和equals()的关系是什么?

如果o1.equals(O2),o1.hashCode()== o2.hashCode()应该永远是真的
如果o1.hashCode()== o2.hashCode, 它并不意味着o1.equals(O2)将是真的

1、hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;

2、如果两个对象相同,就是适用于equals(java.lang.Object) 方法,那么这两个对象的hashCode一定要相同;

3、如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致,否则就会违反上面提到的第2点;

4、两个对象的hashCode相同,并不一定表示两个对象就相同,也就是不一定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”。


再归纳一下就是hashCode是用于查找使用的,而equals是用于比较两个对象的是否相等的。




参考资料:

Java Collection集合面试题

Java常见面试题及答案 21-30(集合类)