文章目录
-
- jdk1.8有那些特性
- JDK1.8中stream用法
- [HashMap 底层原理||工作原理](#HashMap 底层原理||工作原理)
- list,set,map,Queue的区别
- ArrayList与LinkedList,Vector的区别
- Hashtable与HashMap,HashSet的区别
- JAVA中那些集合是线程安全的
- 面向对象三大特征及解释
- 方法覆盖与方法重载的区别
- [10. JAVA接口与抽象类的区别](#10. JAVA接口与抽象类的区别)
jdk1.8有那些特性
- Lambda表达式:简化匿名内部类的编写,支持函数式编程。
- Stream API :提供声明式处理集合数据的能力,支持过滤、映射、归约等操作。比如
filter,sum,max,collect - 新的日期时间API (java.time包):如
LocalDate、LocalTime,LocalDateTime解决旧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<>();
- 创建一个默认长度16的数组,默认加载因子为0.75,数组名table

- 使用元素的哈希值对数组的长度做运算计算出应存入的位置,可以想象这个运算是取余。
- 判断当前位置是否为null,如果是null直接存入

- 如果不为null,表示有元素,则调用equals方法比较相等,则不存入链表;不相等,则存入链表。
- JDK 8之前,新元素存入数组,占老元素位置,老元素挂下面
- JDK 8开始之后,新元素直接使用链表挂在老元素下面。

- 但是如果我们链表过长不就相当于LinkedList了吗。所以当这16个元素被占用了16(当前长度) * 上面第一步的加载因子(0.75) = 12个元素后,会自动扩容。数组扩容为原2倍。
- 但是会有一种可能,我的链表可以一直无限长。但是我的HashSet长度的元素一直没有达到扩容标准。于是加了一个另一个准则:JDK8开始,当链表长度超过8,且数组长度>=64时,自动将链表转成红黑树

哈希计算
- 哈希值 :
hash = key.hashCode() ^ (key.hashCode() >>> 16)(高位参与运算,减少冲突)。 - 数组索引 :
index = hash & (capacity - 1)(等价于取模运算)。
扩容机制
- 触发条件:元素数量 > 容量 × 负载因子(默认0.75)。
- 扩容过程 :
- 新容量 = 旧容量 × 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<>());
面向对象三大特征及解释
- 封装:隐藏类的内部实现细节,对外提供一个可访问的接口。
- 继承 :子类继承父类属性和方法,实现代码复用(如
extends关键字) - 多态:同一种事物,由于条件不同,产生的结果也不同。即同一个引用类型,使用不同的实例而执行不同的操作。
方法覆盖与方法重载的区别
方法重写
- 在父类与子类之间
- 方法名相同
- 参数列表相同
- 返回值类型相同或是其子类
- 访问权限不能严于父类
方法重载
- 在同一个类中
- 方法名相同
- 参数个数或类型不同
- 与返回值和访问修饰符无关
| 比较项 | 位置 | 方法名 | 参数表 | 返回值 | 访问修饰符 |
|---|---|---|---|---|---|
| 方法重写 | 子类 | 相同 | 相同 | 相同或是其子类 | 不能比父类更严格 |
| 方法重载 | 同类 | 相同 | 不相同 | 无关 | 无关 |
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继承 |