Java知识

值传递和引用传递

  • 实际上只有值传递,传递值的副本
  • 引用传递是传递地址作为值的副本,所以修改成员会影响原来的对象
  • 基本类型值传递;引用类型(对象,数组等)引用传递

int 和 Integer

int 是基本数据类型,直接计算
Integer 是 Integer 对象,用各种方法
Integer.parseInt(String s)将字符串转为 int(基本类型)
Integer.max(int a, int b)返回较大值
Integer.toString(a)转换成字符串

1
2
3
4
5
6
7
8
9
10
int a = 10;         // 基本类型,值直接是 10
Integer b = 10; // 自动装箱(推荐写法)

String s1 = Integer.toString(a); // 转换成字符串
String s2 = b.toString();

Integer i = 100; // 自动装箱:int → Integer
int j = i; // 自动拆箱:Integer → int

Integer.valueOf(100) //返回一个表示数值 100 的 Integer对象

Java 类中的静态变量和静态方法

在 Java 中,静态变量和静态方法是与类本身关联的
而不是与类的实例关联。它们在内存中只存在一份,可以被类的所有实例共享

Java 里面的引用类型

Java 的所有非基本类型都是 引用类型(对象通过引用访问)
Collection 是 List,Set,Queue 等接口的根接口;Map 是 HashMap 和 TreeMap 等类实现的根接口

Java 类型 C++ 对应类型 JAVA 功能描述
String std::string 不可变对象(immutable),通过引用操作
int[] 原生数组或std::vector 数组是对象,带长度属性(arr.length),自动内存管理
List<T> (如 ArrayList) std::vector<T> List是接口,ArrayList是动态数组实现
Map<K,V> (如 HashMap) std::unordered_map<K,V> HashMap基于哈希表,无序
Set<T> (如 HashSet) std::unordered_set<T> HashSet基于哈希表,无序且唯一
自定义类(class Person class Person 对象通过引用访问(类似智能指针)

Java 引用类型的使用
字符串:String name = "Alice";
动态数组:List<Integer> numbers = new ArrayList<>();
哈希表:Map<String, Integer> map = new HashMap<>();
自定义类:Person person = new Person("Alice", 18);

接口复用代码

Java 只有单继承(extends ),但可以实现(implements) 多个接口

从 Java 8 开始接口可以有:

  • 默认方法(default):提供默认实现
  • 静态方法(static):工具方法
  • 私有方法(private):默认辅助方法

用接口复用代码的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
interface Flyable {
// 默认实现!子类不用重写也可以直接用
default void takeOff() {
System.out.println("Taking off...");
}

// 抽象方法(必须实现)
void fly();
}

class Bird implements Flyable {
@Override
public void fly() {
System.out.println("Bird is flapping wings.");
}
// 注意:takeOff()自动继承!
}

public class Main {
public static void main(String[] args) {
Bird bird = new Bird();
bird.takeOff(); // 直接调用接口的默认方法!
bird.fly();
}
}

lambda 表达式

Java 8 引入了 lambda 表达式
简化了匿名内部类的写法
(a, b) -> a + b
(a, b) -> {a + b; return a + b;}// 多条语句要用{}

stream 的 API

适合集合对象的操作,如过滤,映射,排序,聚合等

问题场景:从一个列表中筛选出所有长度大于 3 的字符串,并收集到一个新的列表中。
没有 Stream 啲做法:

1
2
3
4
5
6
7
8
List<String> originalList = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
List<String> filteredList = new ArrayList<>();

for (String s : originalList) {
if (s.length() > 3) {
filteredList.add(s);
}
}

使用 Stream API 的做法:

1
2
3
4
List<String> originalList = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
List<String> filteredList = originalList.stream()
.filter(s -> s.length() > 3)
.collect(Collectors.toList());
  1. originalList.stream():创建一个流,该流包含原始列表中的所有元素。
  2. .filter(s -> s.length() > 3):对流进行过滤,只保留长度大于 3 的字符串。
  3. .collect(Collectors.toList()):将过滤后的结果收集到一个新的列表中。

其他案例:字符串统一排序

  1. map(s -> s.toUpperCase()):将每个字符串转换为大写。
  2. .sorted():对字符串进行排序。
  3. .collect(Collectors.joining(", ")):将排序后的字符串连接成一个字符串,并使用逗号(,)作为分隔符。

计算数字列表的和

  1. numbers.stream():创建一个流,该流包含原始列表中的所有数字。
  2. .mapToInt(Integer::intValue):将数字映射为 int 类型。
  3. .sum():计算数字的和。

cpu 密集的运算用 Stream 并行
I/O 密集的运算用 Stream 串行

终端操作

终端操作是流管道(stream pipeline)中的最后一个操作,是触发流管道执行的操作。
一旦调用,流就被 消费(consumed),不能再被使用。
与中间操作(如 filter, map)不同,终端操作 不返回 Stream,而是返回

所有 Java stream API 的终端操作

类别 方法 功能说明 返回类型 是否短路
遍历 / 副作用 forEach(action) 对每个元素执行操作(并行流中无序) void
forEachOrdered(action) 按照流的原始顺序执行操作(即使并行流也保序) void
收集结果 collect(Collectors.toList())
(典型用法)
将流元素收集到 List(也可 toSet(), joining() 等) R(如 List<T>
toArray() 转为 Object[] 数组 Object[]
toArray(String[]::new)
(示例)
转为指定类型数组(如 String[] T[]
归约 reduce(初始值, 累加器) 从初始值开始,依次合并元素(如字符串拼接、求和) T
reduce(累加器) 无初始值归约,流为空时返回 Optional.empty() Optional<T>
查找与匹配 findFirst() 返回第一个元素(适合有序流) Optional<T> ✅ 是
findAny() 返回任意一个元素(适合并行流,更快) Optional<T> ✅ 是
anyMatch(pred) 是否存在至少一个元素满足条件 boolean ✅ 是
allMatch(pred) 是否所有元素都满足条件 boolean ✅ 是(遇到 false 即停)
noneMatch(pred) 是否没有元素满足条件 boolean ✅ 是(遇到 true 即停)
min(comparator) 返回最小元素(按比较器) Optional<T>
max(comparator) 返回最大元素 Optional<T>
计数 count() 返回流中元素总数 long

中间操作

类别 方法 功能说明 返回类型
过滤 filter(Predicate<? super T> predicate) 保留满足条件的元素 Stream<T>
映射 / 转换 map(Function<? super T, ? extends R> mapper) 将每个元素转换为另一种类型 Stream<R>
flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) 将每个元素映射为一个流,然后扁平化合并为一个流 Stream<R>
mapToInt(ToIntFunction<? super T> mapper) 转为 IntStream(用于基本类型优化) IntStream
mapToLong(...) / mapToDouble(...) 类似,分别转为 LongStream / DoubleStream LongStream / DoubleStream
排序 sorted() 按自然顺序排序(要求元素实现 Comparable Stream<T>
sorted(Comparator<? super T> comparator) 按指定比较器排序 Stream<T>
去重 distinct() 去除重复元素(基于 equals() Stream<T>
截取 limit(long maxSize) 保留前 maxSize 个元素 Stream<T>
skip(long n) 跳过前 n 个元素 Stream<T>
查看 / 调试 peek(Consumer<? super T> action) 对每个元素执行操作(常用于调试),不影响流本身 Stream<T>
并行 / 串行控制 parallel() 将流转换为并行流 Stream<T>
sequential() 将流转换为顺序流 Stream<T>
unordered() 忽略流的顺序性(可能提升并行性能) Stream<T>

责任链模式

一个请求需要多个处理逻辑时的灵活做法
比如各种校验逻辑

先定义一个抽象处理者类

1
2
3
4
5
6
7
8
9
10
// 抽象处理者类
abstract class Handler {
protected Handler next;
// 设置下一个处理节点
public void setNext(Handler next) {
this.next = next;
}
// 抽象处理方法
public abstract boolean handle(Request request);
}

然后每个校验逻辑都继承这个类,比如登录逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 登录态校验节点
class LoginHandler extends Handler {
@Override
public boolean handle(Request request) {
if (request.isLogin()){
System.out.println("登录态校验通过,交给下一个节点");
// 交给下一个节点处理
return next != null ? next.handle(request) : true;
} else {
System.out.println("未登录,返回失败");
// 校验不通过,终止链路
return false;
}
}
}

然后再写其他节点,最后根据需要动态添加节点

1
2
3
4
5
6
7
8
9
10
// 组装链路:登录态校验 -> 权限校验 -> 频率校验
Handler loginHandler = new LoginHandler();
Handler authHandler = new AuthHandler();
Handler rateLimitHandler = new RateLimitHandler();
loginHandler.setNext(authHandler);
authHandler.setNext(rateLimitHandler);

// 创建请求
Request request = new Request(true, "admin", 1);// 已登录,管理员权限,第一次请求
boolean result = loginHandler.handle(request);

这样一来,发起方只需要调用第一个节点,不用关心后面有多少校验步骤
如果某个接口不需要某个校验就直接去掉这个节点就行,非常灵活


Java知识
http://www.981928.xyz/2025/11/14/Java知识/
作者
981928
发布于
2025年11月14日
许可协议