java 面试题

java 面试题

java 集合

  1. ArrayList 和 Vector 的区别
    两者底层都是用Object[]实现存储
    Vector是线程安全的使用了synchronized
    两者扩充策略不同,ArrayList是1.5倍扩充,Vector默认2倍。
    可以通过Collections.synchronized(List list)获取一个线程安全的List

  2. 说说 ArrayList,Vector, LinkedList 的存储性能和特性
    Vector是线程安全的,成倍扩充,性能不是太好
    ArrayList非线程安全,0.5倍扩充,性能比Vector好
    Vector、ArrayList都是Object[]存储元素,随机添加、删除效率低因为要移动元素,查找效率高
    LinkedList是非线程安全的,采用双向链表存元素,随机查询效率低,添加、删除效率高。

  3. 快速失败 (fail-fast) 和安全失败 (fail-safe) 的区别是什么?涉及到多线程并发访问集合。
    在iterator使用时出现
    fail-fast:在迭代器使用时发现集合被其他线程修改就会抛出ConcurrentModificationException异常
    fail-safe:迭代器在使用集合时是对集合的copy操作,不会触发ConcurrentModificationException异常,遍历的集合不会自动更新。

  4. hashmap 的数据结构
    由Node<K,V>[] 、链表、红黑树组成。默认Node[]长度16位。
    Node类表示一个元素,包含key、value、hash、next属性,next指向hashcode相同所在Node[]中同一位置的其他元素。相同位置的Node存储为一个链表,链表默认最长8位,超过将改外红黑树存储。jdk1.8Node[]成倍扩充,在resize时重新计算元素位置时要么元素位置不变,要么增加了扩充前数组长度的偏移量。

    补充:
    hash:把任意长度的输入通过散列算法转为固定长度的输出
    &:位运算,操作数同为1,结果是1,否则为0。使用Node[]长度-1 & hashcode 计算元素保存位置,好处是保证计算结果不会超出数组长度,尽量减少冲突。由于数组长度是2的倍数,数组长度-1的值全部为1

  5. HashMap 的工作原理是什么?
    HashMap 使用一个Node[]数组来保存元素。
    当往HashMap中put一个元素时,会先根据key计算hash值,用数组长度-1&(位运算与)hash值,得到的即是这个元素对应的数组下标,如果Node数组在这个下标中没有元素,则根据key、value、hash创建Node对象并保存在数组的下标位置。
    如果数组在这个下标中已经存在元素,并且hashcode 相等,并且key ==相等或equals相等,那么不会增加新元素也不会修改原来的元素。否则在这个Node[]数组位置建立一个链表,将新创建的Node元素添加在已存在Node元素的next上, 链表默认长度8,如果超出则将这些相同位置上的元素转为使用TreeNode红黑树保存。

  6. Hashmap 什么时候进行扩容呢?
    默认加载因子是0.75,当容量使用了0.75倍时进行扩容。

  7. List、Map、Set 三个接口,存取元素时,各有什么特点?
    List 存储单个元素的集合,元素是可重复的。
    Set 存储单个元素的集合,中元素时不可重复的,可以包含null。
    List、Set都是集成的Collection接口
    Map存储的是键值映射对的集合

  8. Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用 == 还是 equals()? 它们有何区别?
    都用到了,HashSet底层使用的HashMap作为容器,将元素作为key,保存到HashMap中,HashMap添加元素时会判断key的hash值是否相同、判断key 是否== ,或者equals()相等,如果不相等才会添加。
    == 如果比较基本类型时byte、short、char、int、long、float、double、boolean比较的是值,引用类型时比较的是堆内存地址是否相等
    equals() 是基类Object的方法,默用==进行比较,但是可以被子类重写

  9. 两个对象值相同 (x.equals(y) == true),但却可有不同的 hash code,这句话对不对?
    不对,java规范中要求 两个对象equals()相等时,它们的hashCode值要相同。但是有相同hashCode的两个对象不一定是equals的。

  10. heap 和 stack 有什么区别。
    stack 栈内存,为线程执行所创建的存储区域,当进入一个方法时创建一个内存区块(栈帧),保存方法的参数、局部变量(基本类型、引用类型)、中间计算过程等,栈块的大小是已知的,将这个内存区块压入栈,栈中的数据是先进后出的,所以追踪栈的使用比较方便。栈中变量使用完后,栈中的空间被立即释放,引用的堆中的空间等待GC释放,方法结束后区块内存被释放。
    heap 堆内存,用来动态分配的存储区域,被所有线程共同使用,存放创建出来的对象和数组。栈内存中的引用对象的实例保存在堆内存中。堆内存由垃圾回收器回收。

  11. Java 集合类框架的基本接口有哪些?
    Collection 、Map
    Collection:是元素集合
    Map:是键值对
    List、Set继承Collection
    List:可重复
    Set:不可重复

  12. HashSet 和 TreeSet 有什么区别?
    HashSet :使用HashMap存储元素
    TreeSet:实现了SortedSet接口,元素是有序的

  13. HashSet 的底层实现是什么?
    底层用的HashMap保存元素,使用key作为Node<k,v>的键值。通过HashMap的key是唯一的来保证HashSet不能有重复的元素

  14. LinkedHashMap 的实现原理?
    与HashMap比较相似,不同的是LinkedHashMap可以保存元素之间的顺序,默认按照插入的顺序。多了2个属性head、tail保存第一个和最后一个元素
    LinedHashMap依然使用Node<k,v>[]保存元素,但是每个元素又形成了一个双向链表。其Node类继承类HashMap使用的Node类,增加了before、after两个属性连接前后的Node对象,每添加新元素时,将按照顺序插插入到双向链表里,但仍然按照hashcode计算所在Node[]中的位置。如果hashcode发生碰撞处理方法与HashMap一致

  15. 为什么集合类没有实现 Cloneable 和 Serializable 接口?
    集合的接口没有继承Cloneable和Serializable接口,因为集合的本意是保存一系列元素的容器。其他特性可以在具体实现类来添加.。Cloneable和Serizlizable接口都没有定义方法,只是为jvm提供了一个标识,标识可以进行备份和序列化操作。
    Cloneable接口:
    实现了Cloneable接口的类可以使用clone方法生成一个对象的拷贝(非引用)对象,如果类没有提供clone()方法将使用Object默认的clone()方法,Object提供的clone方法,是native的,效率会高一些,Object.clone() 是浅拷贝。
    ArrayList的clone()方法使用的是Object.clone(),然后再用Arrays.copyOf()来拷贝集合元素,来创建集合,由于这2个方法都是浅拷贝,如果存储对象元素将会影响原来的集合。
    HashMap也是先用Object.clone()克隆本类对象,再用原集合的元素创建新集合的元素,都是浅拷贝。

    Serializable接口:
    实现Serializable接口的类的对象可以被序列化、和反序列化。序列化是将对象转为字节流,用来存储或网络传输给另一个系统。反序列化可以将字节流还原回对象。序列化时对象的引用类型字段也要实现序列化接口才可以。
    ArrayList、HashMap的集合存储属性都是transient的,通过自定义writeObject、readObject来序列化和反序列化

  16. 什么是迭代器 (Iterator)?
    Iterator接口为容器对象提供了统一的遍历元素的功能,使用它不用关心底层数据结构。通过hasNext()、next() 方法遍历集合元素,提供了remove()方法可以在迭代元素时删除集合中的元素。

  17. Iterator 和 ListIterator 的区别是什么?
    ListIterator接口继承了Iterator接口,提供了set()、add()、hasPrevious() 、previous()、nextIndex()、previousIndex()等方法,可以向前也可以向后遍历,也可以修改和新增元素。
    Iterator可以用在List、Set、Map子类中,ListIterator只能用在List子类中

  18. 数组 (Array) 和列表 (ArrayList) 有什么区别?什么时候应该使用 Array 而不是 ArrayList?
    Array: 可以存储基本类型和对象,长度是固定的,可以是多维数组,不支持泛型
    ArrayList: 底层存储使用的是Array Object[]只能存储对象类型,基本类型会自动装箱为封装类。长度是可扩展的,支持泛型,提供了更多方法addAll()、removeAll()等。
    处理固定长度的基本类型数据时可以使用Array,省去装箱操作

  19. Java 集合类框架的最佳实践有哪些?
    固定元素数量的集合使用Array
    随机删除、插入元素较多时使用LinkedList,一般使用ArrayList,不能重复的使用HashSet
    键值对使用Map,有序key使用TreeMap,其他使用HashMap

  20. Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢?是用 == 还是 equals()?它们有何区别?
    HashSet 使用的 HashMap作为底层存储,key为元素。在add添加元素时使用HashMap的put方法保存元素会判断key的hash是否相等()以及判断key本身是否相等或equals。这也证明了java中equals的对象的hashcode也要相同的约定。因此判断元素是不是重复即用到了也用到了equals。

  21. Comparable 和 Comparator 接口是干什么的?列出它们的区别
    Comparable接口,提供了一个 int compareTo(T o) 方法 ,其实现类对象之间可以互相比较大小,返回正数比较者大于被比较者,返回负数小于,返回0等于
    Comparator接口,比较器接口实现这个接口的类,可以对外提供比较2个相同类型对象的功能。

  22. Collection 和 Collections 的区别。
    Collection 是集合的最基本接口,提供集合基本操作
    Collections 是一个工具类,提供了操作集合的静态方法,如排序、查找,提供了创建同步集合类的方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值