Collectors.joining() 是用于将流中的字符串元素连接成一个字符串的收集器。它有多个重载版本,提供不同的连接方式。
三个主要重载版本
java
// 1. 最简单的版本 - 直接连接
public static Collector<CharSequence, ?, String> joining()
// 2. 指定分隔符
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter)
// 3. 指定分隔符、前缀和后缀
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix)基本用法
java
List<String> fruits = Arrays.asList("apple", "banana", "cherry");
// 1. 直接连接(无分隔符)
String noDelimiter = fruits.stream()
.collect(Collectors.joining());
System.out.println("直接连接: " + noDelimiter); // "applebananacherry"
// 2. 用逗号分隔
String withComma = fruits.stream()
.collect(Collectors.joining(", "));
System.out.println("逗号分隔: " + withComma); // "apple, banana, cherry"
// 3. 用分隔符、前缀和后缀
String withAll = fruits.stream()
.collect(Collectors.joining(", ", "[", "]"));
System.out.println("完整格式: " + withAll); // "[apple, banana, cherry]"
// 4. 复杂分隔符
String complex = fruits.stream()
.collect(Collectors.joining(" -> "));
System.out.println("箭头分隔: " + complex); // "apple -> banana -> cherry"核心特性
1. 处理 null 值
java
List<String> words = Arrays.asList("Hello", null, "World", null, "!");
// ❌ 包含 null 值会抛出 NullPointerException
// String bad = words.stream().collect(Collectors.joining(" "));
// ✅ 先过滤 null 值
String good = words.stream()
.filter(Objects::nonNull) // 过滤 null
.collect(Collectors.joining(" "));
System.out.println("过滤 null: " + good); // "Hello World !"
// ✅ 使用 map 将 null 转换为空字符串
String withDefault = words.stream()
.map(word -> word != null ? word : "") // 映射,替换成空串
.collect(Collectors.joining(" "));
System.out.println("null 转空字符串: " + withDefault); // "Hello World !"
// ✅ 使用 map 将 null 转换为占位符
String withPlaceholder = words.stream()
.map(word -> word != null ? word : "(null)") // 映射
.collect(Collectors.joining(", "));
System.out.println("使用占位符: " + withPlaceholder);
// "Hello, (null), World, (null), !"2. 空流处理
java
// 空流直接连接
String empty = Stream.<String>empty()
.collect(Collectors.joining());
System.out.println("空流: '" + empty + "'"); // ""
// 空流带分隔符
String emptyWithDelimiter = Stream.<String>empty()
.collect(Collectors.joining(", "));
System.out.println("空流带分隔符: '" + emptyWithDelimiter + "'"); // ""
// 空流带前缀后缀
String emptyWithWrapper = Stream.<String>empty()
.collect(Collectors.joining(", ", "[", "]"));
System.out.println("空流带包装: '" + emptyWithWrapper + "'"); // "[]"
// 只有一个元素
String single = Stream.of("apple")
.collect(Collectors.joining(", ", "[", "]"));
System.out.println("单个元素: '" + single + "'"); // "[apple]"
// 两个元素
String two = Stream.of("apple", "banana")
.collect(Collectors.joining(", ", "[", "]"));
System.out.println("两个元素: '" + two + "'"); // "[apple, banana]"3. 与其他操作的链式调用
java
List<String> names = Arrays.asList("alice", "bob", "charlie", "diana");
// 链式操作:过滤 -> 转换 -> 连接
String result = names.stream()
.filter(name -> name.length() > 3) // 长度大于3
.map(String::toUpperCase) // 转为大写
.sorted() // 排序
.collect(Collectors.joining(" | ")); // 连接
System.out.println("链式操作结果: " + result);
// "ALICE | CHARLIE | DIANA"
// 更复杂的链式操作
String complex = names.stream()
.map(name -> name.substring(0, 1).toUpperCase() + name.substring(1))
.sorted(Comparator.comparingInt(String::length).reversed())
.collect(Collectors.joining("\n - ", "Names:\n - ", "\nEnd of list"));
System.out.println(complex);
// Names:
// - Charlie
// - Diana
// - Alice
// - Bob
// End of list与其他方法的对比:
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Collectors.joining() | 简洁,链式调用 | 可能内存占用大 | Stream API 中的字符串连接 |
| StringBuilder | 性能最佳 | 代码较冗长 | 非流场景,性能要求高 |
| StringJoiner | 灵活控制格式 | 需要额外创建对象 | 需要自定义分隔符和前后缀 |
| String.join() | 最简单 | 功能有限 | 集合直接连接 |
朔风