Java全栈面试题及答案汇总(3)

文章目录

jdk1.8有那些特性

  • Lambda表达式:简化匿名内部类的编写,支持函数式编程。
  • Stream API :提供声明式处理集合数据的能力,支持过滤、映射、归约等操作。比如filtersummaxcollect
  • 新的日期时间API (java.time包):如LocalDateLocalTimeLocalDateTime解决旧Date类的线程安全问题。
  • 默认方法 :允许在接口中定义具体实现方法,便于接口扩展。接口的方法使用default关键字修饰
  • 函数式接口 :Lambda 表达式的使用前提,是一种特殊的接口。可使用@FunctionalInterface修饰
  • Optional类 :用于避免空指针异常,封装可能为null的值。Optional.ofNullable(T t),orElse(T t)
  • HashMap 底层优化(红黑树)

静态方法引用:ClassName::staticMethod

实例方法引用(特定对象):instance::method

任意对象的实例方法引用:ClassName::instanceMethod

构造方法引用:ClassName::new

JDK1.8中stream用法

Stream是JDK 1.8中用于处理集合数据的API,支持函数式编程风格。常用用法包括:

  • 创建Stream:通过集合的 stream() 方法或 Stream.of() 创建。
  • 中间操作:如 filter() (过滤)、 map() (映射)、 sorted() (排序),这些操作返回新Stream,可链式调用。
  • 终端操作:如 collect() (收集为集合)、 forEach() (迭代)、 reduce() (归约),触发实际计算。
  • 示例: list.stream().filter(x -> x > 0).map(x -> x *
    2).collect(Collectors.toList()) 过滤正数并加倍后收集到列表。
    Stream具有惰性求值特性,提高处理效率。

HashMap 底层原理||工作原理

HashMap基于哈希表实现,工作原理如下:

HashMap底层结构(JDK 8)

  • 数组 + 链表 + 红黑树
    • 数组:默认容量16(2^4),存储Node节点(包含hash、key、value、next)。
    • 链表:哈希冲突时链接相同索引的节点,长度>8转为红黑树。
    • 红黑树:优化长链表查询性能,时间复杂度从O(n)降至O(log n)。

基于哈希表存储数据的。

哈希表

JDK8之前,哈希表 = 数组+链表

JDK8开始,哈希表 = 数组+链表+红黑树

哈希表是一种增删改查数据,性能都较好的数据结构

java 复制代码
Set<String> set = new HashSet<>();
  1. 创建一个默认长度16的数组,默认加载因子为0.75,数组名table
  2. 使用元素的哈希值对数组的长度做运算计算出应存入的位置,可以想象这个运算是取余。
  3. 判断当前位置是否为null,如果是null直接存入
  4. 如果不为null,表示有元素,则调用equals方法比较相等,则不存入链表;不相等,则存入链表。
    • JDK 8之前,新元素存入数组,占老元素位置,老元素挂下面
    • JDK 8开始之后,新元素直接使用链表挂在老元素下面。
  5. 但是如果我们链表过长不就相当于LinkedList了吗。所以当这16个元素被占用了16(当前长度) * 上面第一步的加载因子(0.75) = 12个元素后,会自动扩容。数组扩容为原2倍。
  6. 但是会有一种可能,我的链表可以一直无限长。但是我的HashSet长度的元素一直没有达到扩容标准。于是加了一个另一个准则:JDK8开始,当链表长度超过8,且数组长度>=64时,自动将链表转成红黑树

哈希计算

  1. 哈希值hash = key.hashCode() ^ (key.hashCode() >>> 16)(高位参与运算,减少冲突)。
  2. 数组索引index = hash & (capacity - 1)(等价于取模运算)。

扩容机制

  1. 触发条件:元素数量 > 容量 × 负载因子(默认0.75)。
  2. 扩容过程
    • 新容量 = 旧容量 × 2(翻倍)。
    • 重新计算每个元素的索引,复制到新数组。
    • JDK 8优化:元素要么留在原索引,要么移至原索引 + 旧容量。

list,set,map,Queue的区别

java 复制代码
Java 集合框架
├── Collection(单元素集合根接口)接口
│   ├── List(有序、可重复)接口
│   ├── Set(无序/有序、不可重复)接口
│   └── Queue(有序、按特定规则存取,可重复)接口
└── Map(键值对集合根接口,独立体系)接口
    ├── HashMap(哈希无序、key不可重复)实现类
    ├── LinkedHashMap(保留插入顺序、key不可重复)实现类
    └── TreeMap(key排序有序、key不可重复)实现类

这些是Java集合框架的核心接口,区别如下:

  • List:有序集合,元素可重复,支持索引访问。实现类有ArrayList、LinkedList。
  • Set:无序集合(某些实现如TreeSet有序),元素不可重复。实现类有HashSet、TreeSet。
  • Map:键值对集合,键不可重复,值可重复。实现类有HashMap、TreeMap。
  • Queue:队列,通常遵循先进先出(FIFO)或优先级顺序。实现类有LinkedList、PriorityQueue。

主要区别在于元素顺序、重复性和存储结构。

ArrayList与LinkedList,Vector的区别

  • ArrayList:基于动态数组,支持随机访问(通过索引),时间复杂度O(1);但插入和删除元素需移动后续元素,平均O(n)。非线程安全。
  • LinkedList:基于双向链表,插入和删除元素效率高(只需修改指针),平均O(1);但随机访问需遍历链表,平均O(n)。非线程安全。
  • Vector:类似ArrayList,但线程安全(方法使用synchronized修饰),性能较低。在现代Java中,通常用CopyOnWriteArrayList替代。

Hashtable与HashMap,HashSet的区别

类名 所属接口 存储形式 线程安全 null 值支持 底层结构 核心用途
HashMap Map <Key, Value> 1 个 null Key + 多个 null Value 数组 + 链表 + 红黑树(JDK1.8+) 普通键值对存储(高性能)
Hashtable Map <Key, Value> 不允许 null Key /null Value 数组 + 链表(无红黑树优化) 老旧系统兼容(现已过时)
HashSet Set 单个元素 E 1 个 null 元素(依赖 HashMap) 封装 HashMap(Key 存元素) 元素去重(无需关联额外数据)

JAVA中那些集合是线程安全的

  • 传统集合:Vector、Hashtable、Stack(通过synchronized实现)
  • Collections 工具类包装:
    • Collections.synchronizedList(new ArrayList())
    • Collections.synchronizedSet(new HashSet())
    • Collections.synchronizedMap(new HashMap())
  • JUC包 (并发编程核心工具包)中的并发集合:
    • ConcurrentHashMap :分段锁实现的线程安全Map
    • CopyOnWriteArrayList :写时复制的List
    • CopyOnWriteArraySet :写时复制的Set
    • ConcurrentLinkedQueue :无锁队列
    • BlockingQueue implementations:如ArrayBlockingQueue、LinkedBlockingQueue
java 复制代码
// 将 ArrayList 包装为线程安全的 List
List<String> safeList = Collections.synchronizedList(new ArrayList<>());
// 将 HashMap 包装为线程安全的 Map
Map<String, Integer> safeMap = Collections.synchronizedMap(new HashMap<>());

面向对象三大特征及解释

  1. 封装:隐藏类的内部实现细节,对外提供一个可访问的接口。
  2. 继承 :子类继承父类属性和方法,实现代码复用(如extends关键字)
  3. 多态:同一种事物,由于条件不同,产生的结果也不同。即同一个引用类型,使用不同的实例而执行不同的操作。

方法覆盖与方法重载的区别

方法重写

  1. 在父类与子类之间
  2. 方法名相同
  3. 参数列表相同
  4. 返回值类型相同或是其子类
  5. 访问权限不能严于父类

方法重载

  1. 在同一个类中
  2. 方法名相同
  3. 参数个数或类型不同
  4. 与返回值和访问修饰符无关
比较项 位置 方法名 参数表 返回值 访问修饰符
方法重写 子类 相同 相同 相同或是其子类 不能比父类更严格
方法重载 同类 相同 不相同 无关 无关

10. JAVA接口与抽象类的区别

两者能包含的成员类型有明确区别,具体对比如下:

成员类型 抽象类(Abstract Class) 接口(Interface)
成员变量 可以有普通实例变量、静态变量 仅能有 public static final 常量(默认修饰符,可省略)
构造方法 有构造方法(用于子类初始化父类成员) 无构造方法(接口不能被实例化,也无需初始化成员)
普通方法 可以有普通成员方法(有完整实现) Java 8 前:无;Java 8 后:可包含 default 默认方法(有实现)
抽象方法 可以有抽象方法(abstract 修饰,无实现) Java 8 前:仅能有抽象方法(默认 public abstract,可省略);Java 8 后:仍支持抽象方法
静态方法 可以有静态方法(有实现) Java 8 后:可包含静态方法(有实现,仅接口自身可调用)
私有方法 可以有私有方法(Java 7+,用于内部复用) Java 9 后:可包含私有方法(用于默认方法间的代码复用)
继承性 一个类可以实现多个接口 一个类只能继承一个抽象类
关键字 使用 implements实现 使用 extends继承
相关推荐
SunnyDays101114 小时前
Java 高效实现 CSV 转 PDF
java·csv转pdf
菩提祖师_14 小时前
量子机器学习在时间序列预测中的应用
开发语言·javascript·爬虫·flutter
刘975314 小时前
【第22天】22c#今日小结
开发语言·c#
隐形喷火龙14 小时前
SpringBoot 异步任务持久化方案:崩溃重启不丢任务的完整实现
java·spring boot·后端
我是koten14 小时前
K8s启动pod失败,日志报非法的Jar包排查思路(Invalid or corrupt jarfile /app/xxxx,jar)
java·docker·容器·kubernetes·bash·jar·shell
WX-bisheyuange14 小时前
基于Spring Boot的库存管理系统的设计与实现
java·spring boot·后端
明天好,会的14 小时前
分形生成实验(三):Rust强类型驱动的后端分步实现与编译时契约
开发语言·人工智能·后端·rust
YanDDDeat14 小时前
【JVM】类初始化和加载
java·开发语言·jvm·后端
码农水水14 小时前
阿里Java面试被问:单元测试的最佳实践
java·面试·单元测试