Java集合框架高频面试题及详细答案(实战版)_第1页
Java集合框架高频面试题及详细答案(实战版)_第2页
Java集合框架高频面试题及详细答案(实战版)_第3页
Java集合框架高频面试题及详细答案(实战版)_第4页
Java集合框架高频面试题及详细答案(实战版)_第5页
已阅读5页,还剩2页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java集合框架高频面试题及详细答案(实战版)一、基础概念类1.Java集合框架有哪些核心体系?区别是什么?Java集合主要分为两大核心体系:Collection单列集合和Map双列集合,所有集合工具类都基于这两个顶层接口扩展。1.Collection(存储单个元素)List:有序、可重复、支持索引。核心实现:ArrayList、LinkedList、VectorSet:无序、不可重复、无索引。核心实现:HashSet、LinkedHashSet、TreeSetQueue:队列集合,先进先出,用于场景化数据排队。核心实现:ArrayDeque、LinkedList2.Map(存储键值对K-V)键唯一、值可重复、无索引。核心实现:HashMap、LinkedHashMap、TreeMap、Hashtable核心区别:Collection存单个对象,Map存键值对;List可重复有序,Set不可重复无序。2.数组和集合的区别?日常开发怎么选择?核心区别:长度:数组长度固定,集合长度动态可变存储类型:数组可存基本类型+引用类型;集合只能存引用类型(基本类型会自动装箱)方法:数组只有少数自带方法;集合提供大量增删改查、排序、遍历工具方法泛型:数组无泛型,存在类型不安全问题;集合支持泛型,编译期校验类型选择原则:固定数据量、基础类型优先用数组;数据量不确定、需要频繁增删查改、做业务数据存储一律用集合。3.迭代器Iterator的原理和使用注意事项?Iterator是Java集合的通用遍历工具,所有Collection集合都实现了迭代器遍历,核心作用是统一集合遍历方式,解耦集合和遍历逻辑。核心方法:hasNext():判断是否还有下一个元素next():获取下一个元素remove():删除当前遍历到的元素重点注意(高频坑点):遍历过程中不能直接通过集合对象增删元素,会触发ConcurrentModificationException并发修改异常;只能用迭代器自身的remove()方法删除。增强for循环底层也是迭代器,同样不支持遍历中修改集合。二、List集合核心面试题1.ArrayList和LinkedList的底层区别、性能对比、适用场景?1.底层数据结构ArrayList:动态扩容数组LinkedList:双向链表2.性能差异查询(get):ArrayList快,数组支持随机访问,通过索引直接定位元素;LinkedList需要从头/尾遍历查找,时间复杂度O(n)增删(add/remove):首尾增删LinkedList更快,仅修改节点指针;ArrayList会触发数组移位、扩容,效率低内存消耗:ArrayList会预留冗余容量,存在内存浪费;LinkedList每个节点存储数据+前后指针,单个元素内存占用更大3.适用场景ArrayList:频繁查询、遍历,少量增删(绝大多数业务场景首选)LinkedList:频繁首尾增删、批量操作,极少查询的场景2.ArrayList的扩容机制?默认初始容量、扩容比例是多少?JDK1.8及以上ArrayList核心扩容规则:默认初始容量:创建空参对象时,初始为空数组;第一次添加元素时,初始化容量为10扩容比例:每次扩容为原容量的1.5倍(原容量+原容量右移1位)最大容量:最大支持Integer.MAX_VALUE-8,避免内存溢出扩容流程:添加元素前判断数组容量是否足够→不足则计算新容量→调用Arrays.copyOf复制原数组元素到新数组→完成扩容赋值。实战优化:如果提前预知数据量,建议使用带初始容量的构造方法,减少频繁扩容和数组复制带来的性能损耗。3.ArrayList、Vector、Stack的区别?ArrayList:线程不安全,效率高,日常开发首选Vector:线程安全(所有方法加synchronized),效率极低,基本废弃;默认扩容2倍,比ArrayList更浪费内存Stack:继承Vector,实现栈结构(后进先出),线程安全但性能差,业务中推荐用ArrayDeque替代三、Set集合核心面试题1.HashSet去重原理?为什么必须重写equals和hashCode方法?HashSet底层原理:底层基于HashMap实现,添加元素时,本质是向HashMap存入key(当前元素)、value(固定占位对象)。去重流程:调用对象的hashCode()方法,计算哈希值,确定数组存储位置判断该位置是否为空,为空则直接存入元素位置已有元素,调用equals()方法对比内容equals返回true,判定为重复元素,不存入;返回false,发生哈希冲突,挂链表/红黑树存储为什么必须重写两个方法:如果只重写equals不重写hashCode:两个内容相同的对象,默认hashCode不同,会被判定为两个不同元素,无法去重;如果只重写hashCode不重写equals:不同对象哈希值相同,会被误判为重复,导致元素丢失。结论:业务实体类只要涉及集合去重,必须同时重写hashCode和equals。2.HashSet、LinkedHashSet、TreeSet的区别?HashSet:无序、不可重复,底层HashMap,查询增删效率最高,无排序功能LinkedHashSet:有序(插入顺序)、不可重复,底层LinkedHashMap,保留元素添加顺序,性能略低于HashSetTreeSet:自然排序/自定义排序、不可重复,底层TreeMap,基于红黑树,增删查询效率略低,支持自动排序适用场景:无需排序用HashSet;需要保留插入顺序用LinkedHashSet;需要自动排序用TreeSet。3.TreeSet排序规则?自定义排序怎么实现?TreeSet支持两种排序方式,优先级:自定义比较器>自然排序自然排序:实体类实现Comparable接口,重写compareTo方法,定义默认排序规则自定义排序:创建TreeSet时传入Comparator比较器,重写compare方法,临时指定排序规则注意:TreeSet去重依据排序方法的返回值,返回0则判定为重复元素,而非equals方法。四、Map集合核心面试题(重中之重)1.HashMap底层数据结构?JDK1.7和JDK1.8核心区别?底层结构:哈希表(数组+链表+红黑树)JDK1.7结构:数组+单向链表,无红黑树JDK1.8核心优化(面试高频):数据结构升级:数组+链表+红黑树,解决链表过长查询慢的问题树化规则:链表长度大于8,且数组容量大于64,链表转为红黑树;链表长度小于6,退化为链表插入方式:1.7头插法,1.8尾插法,彻底解决多线程扩容环形链表死循环问题扩容优化:1.8无需重新计算哈希值,通过高位运算确定新下标,效率更高初始容量优化:1.8空参创建对象不初始化数组,首次put才初始化,节省内存2.HashMap工作原理?put方法完整流程?整体流程:哈希寻址→判空存入→冲突遍历→树化判断→覆盖/新增→扩容校验首次调用put方法,初始化数组,默认容量16根据key的hashCode计算哈希值,通过哈希算法算出数组下标判断当前下标位置元素是否为空,为空直接存入键值对位置已有元素,判断key是否相同(hash一致+equals一致),相同则覆盖value值key不同,遍历链表/红黑树:链表尾部插入新节点;树结构则按树规则插入插入完成后,判断链表长度是否满足树化条件,满足则转为红黑树最后判断元素总个数是否超过阈值(容量*0.75),超过则触发扩容3.HashMap负载因子0.75的意义?为什么不是0.5或1?负载因子作用:决定HashMap扩容时机,阈值=容量*负载因子,元素数量超过阈值就扩容。0.75是时间和空间的最优平衡:如果是0.5:扩容太频繁,空间利用率低,浪费内存如果是1:填满才扩容,哈希冲突概率极高,链表超长,查询性能大幅下降0.75兼顾了内存利用率和查询效率,是官方最优取值4.HashMap、LinkedHashMap、TreeMap、Hashtable区别?HashMap:线程不安全,无序,效率高,允许key/value为null,日常开发首选LinkedHashMap:继承HashMap,有序(插入顺序/访问顺序),可实现LRU缓存策略TreeMap:基于红黑树,可排序,线程不安全,key不允许为nullHashtable:线程安全(全方法加锁),效率极低,不允许key/value为null,基本废弃5.HashMap线程不安全体现在哪里?怎么解决?线程不安全问题:JDK1.7多线程扩容会出现环形链表死循环,导致CPU100%占用多线程同时put元素,会出现元素覆盖丢失问题并发读写时,可能触发空指针、数据不一致等问题解决方案(面试优先级排序):ConcurrentHashMap(首选):分段锁+CAS,并发效率极高Collections.synchronizedMap:全局加锁,效率低,适合低并发场景Hashtable:性能最差,不推荐使用6.ConcurrentHashMap底层原理?JDK1.8优化点?底层结构:JDK1.8采用数组+链表+红黑树,放弃1.7的分段锁机制核心并发保障:CAS+synchronized锁单个桶位锁粒度细化:只锁住当前操作的数组下标位置,不影响其他位置元素读写,并发效率大幅提升。关键特性:不允许key/value为null,避免空指针歧义支持高并发增删改查,线程安全且性能优异树化、扩容规则与HashMap基本一致五、集合高频坑点与实战面试题1.为什么集合类大多非线程安全?线程安全需要加锁、同步校验,会带来极大的性能损耗。Java设计理念是默认高效,并发场景手动适配。绝大多数业务场景是单线程操作集合,不需要线程安全;仅高并发场景需要使用ConcurrentHashMap等安全集合,兼顾性能和安全。2.遍历集合时删除元素有哪些坑?正确写法是什么?错误写法:普通for循环、增强for循环中直接调用集合remove()方法,大概率触发并发修改异常或漏删、错删。三种正确写法:使用迭代器iterator的remove()方法删除JDK8+使用集合removeIf()lambda方法(最简推荐)普通for倒序遍历删除,避免数组移位导致下标错乱3.Arrays.asList()方法的坑点?该方法返回的是Arrays内部静态类,不是java.util.ArrayList返回的集合长度固定,不支持add、remove、clear方法,调用会抛异常该集合和原数组共用同一内存,修改数组元素会同步影响集合元素解决方案:手动newArrayList<>(Arrays.asList(数组)),转为正常

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论