构造器引用 & 数组引用 & 方法引用组合(AI 辅助学习 Java 8)

34 阅读3分钟

上周学了方法引用基础。今天深入学习数组引用、方法引用组合操作,以及在博客项目中用方法引用让 Stream 代码更加优雅。


一、数组引用

数组也有构造器引用,语法是 Type[]::new

// IntFunction<int[]>: (n) -> new int[n]
IntFunction<int[]> intArray = int[]::new;
int[] numbers = intArray.apply(5);  // [0, 0, 0, 0, 0]

最常用的场景:Stream.toArray()

List<String> words = Arrays.asList("Java", "Lambda", "Stream");

// Lambda 写法
String[] array1 = words.stream().toArray(n -> new String[n]);
// 方法引用写法
String[] array2 = words.stream().toArray(String[]::new);
// 结果: ["Java", "Lambda", "Stream"]

二维数组引用

IntFunction<int[][]> matrix = int[][]::new;
int[][] m = matrix.apply(2);  // int[2][]

二、方法引用组合

方法引用可以和函数式接口的 andThencomposeandor 等方法组合使用。

Function.andThen

Function<String, Integer> parseInt = Integer::parseInt;
Function<Integer, String> toHex = Integer::toHexString;

// 先 parseInt,再 toHexString
Function<String, String> compose = parseInt.andThen(toHex);
compose.apply("255");  // "ff"

Predicate.and / or

Predicate<String> isLong = s -> s.length() > 4;
Predicate<String> startsWithJ = s -> s.startsWith("J");
Predicate<String> combined = isLong.and(startsWithJ);

List<String> words = Arrays.asList("Java", "Lambda", "JavaScript");
words.stream()
        .filter(combined)  // 长度>4 且 以J开头
        .collect(toList());  // ["JavaScript"]

BinaryOperator 组合

BinaryOperator<Integer> max = Integer::max;
List<Integer> nums = Arrays.asList(3, 7, 2, 9, 1);
int maxVal = nums.stream().reduce(0, max);  // 9

三、博客项目进阶重构

1. 提取所有标签(flatMap + List::stream)

// 重构前
List<String> allTags = blogs.stream()
        .flatMap(blog -> blog.getTags().stream())
        .distinct()
        .sorted()
        .collect(toList());

// 重构后
List<String> allTags = blogs.stream()
        .map(BlogPost::getTags)
        .flatMap(List::stream)
        .distinct()
        .sorted()
        .collect(toList());
// 结果: [API, Docker, Java8, Lambda, Optional, Stream, ...]

2. 标签词云(统计出现次数)

Map<String, Long> tagCloud = blogs.stream()
        .map(BlogPost::getTags)
        .flatMap(List::stream)
        .collect(Collectors.groupingBy(s -> s, Collectors.counting()));
// 结果: {Java8=4, Lambda=2, Stream=1, ...}

3. 按分类获取标题列表

Map<String, List<String>> byCategory = blogs.stream()
        .collect(Collectors.groupingBy(
                BlogPost::getCategory,
                Collectors.mapping(BlogPost::getTitle, Collectors.toList())
        ));
// 结果: {Java=[Lambda 入门, Stream 详解, ...], 前端=[Vue3 API], ...}

4. 热门/普通文章分类

Map<Boolean, List<BlogPost>> hotSplit = blogs.stream()
        .collect(Collectors.partitioningBy(BlogPost::isHot));

System.out.println("热门文章: " + hotSplit.get(true).size() + " 篇");
System.out.println("普通文章: " + hotSplit.get(false).size() + " 篇");

5. 格式化输出

// 重构前
blogs.stream()
        .filter(blog -> blog.isPublished())
        .map(blog -> blog.formatSummary())
        .forEach(summary -> System.out.println(summary));

// 重构后
blogs.stream()
        .filter(BlogPost::isPublished)
        .map(BlogPost::formatSummary)
        .forEach(System.out::println);

四、运行结果

=== 数组引用 ===
  int[5]: [0, 0, 0, 0, 0]
  toArray(String[]::new): [Java, Lambda, Stream]
  int[2][3]: 2 行

=== 方法引用组合 ===
  parseInt.andThen(toHexString): ff
  length>4 且以J开头: [JavaScript]
  Integer::max 求最大值: 9

=== 博客项目进阶重构 ===
  所有标签: [API, Docker, Java8, Lambda, Optional, Stream, Vue, 前端, 基础, 空指针, 进阶, 部署, 集合]
  标签词云: {Java8=4, Lambda=2, 基础=2, ...}
  分类标题: {Java=[Lambda 入门, Stream 详解, 方法引用, Optional 实践], 运维=[Docker 部署], 前端=[Vue3 API]}
  热门文章: 2 篇
  普通文章: 4 篇
[Java] Lambda 入门 (200 阅读)
[Java] Stream 详解 (350 阅读)
[前端] Vue3 API (180 阅读)
[Java] 方法引用 (120 阅读)
[Java] Optional 实践 (300 阅读)

五、方法引用速查表

Lambda 写法方法引用写法
s -> s.length()String::length
s -> s.toUpperCase()String::toUpperCase
s -> Integer.parseInt(s)Integer::parseInt
() -> System.currentTimeMillis()System::currentTimeMillis
x -> System.out.println(x)System.out::println
() -> new ArrayList<>()ArrayList::new
s -> new StringBuilder(s)StringBuilder::new
n -> new int[n]int[]::new
blog -> blog.getTitle()BlogPost::getTitle
blog -> blog.isPublished()BlogPost::isPublished
list -> list.stream()List::stream

六、本周学习总结

第七周我们学习了方法引用与构造器引用,完整路线:

周二:方法引用::: 双冒号的四种用法
周四:构造器引用 & 数组引用 & 方法引用组合(本篇)
周六:重构博客项目:方法引用让代码更简洁

核心收获

方法引用类型语法适用场景
对象::实例方法obj::methodLambda 调用已有对象的方法
类::静态方法Class::staticMethodLambda 调用类的静态方法
类::实例方法Class::instanceMethodLambda 的第一个参数是调用者
类::newClass::newLambda 只创建一个对象
数组::newType[]::new创建数组,最常用在 toArray()

关键原则

  • 方法引用不是新功能,只是 Lambda 的语法糖
  • 只在 Lambda 体只做一件事时使用
  • 可读性优先,不要为了用方法引用而用

七、下周预告

第八周进入 默认方法 & 静态接口方法,了解接口如何拥有方法体,以及多继承冲突如何解决。


系列文章导航

更多请关注我的微信公众号,感谢!

微信图片_20260427132414_18_737.jpg