Can be replaced with 'Collectors.joining'
Can be replaced with ‘Collectors.joining’
Can be replaced with ‘Collectors.joining’
Can be replaced with ‘Collectors.joining’
這個警告是在提醒你,當前使用的字串拼接或累加邏輯可以用 Collectors.joining()
來更簡潔、更高效地實現。
- 使用 StringBuilder 在 Stream 中拼接
// ❌ 可以改善的寫法
StringBuilder sb = new StringBuilder();
list.stream().forEach(item -> sb.append(item).append(“, “));
String result = sb.toString();
// ✅ 使用 Collectors.joining()
String result = list.stream()
.collect(Collectors.joining(“, “));
2. 使用 reduce() 進行字串累加
// ❌ 效率不佳的寫法
String result = list.stream()
.reduce(“”, (a, b) -> a + “, “ + b);
// ✅ 更好的寫法
String result = list.stream()
.collect(Collectors.joining(“, “));
3. 傳統的迴圈拼接
// ❌ 傳統寫法
List
StringBuilder sb = new StringBuilder();
for (int i = 0; i < names.size(); i++) {
if (i > 0) {
sb.append(“, “);
}
sb.append(names.get(i));
}
String result = sb.toString();
// ✅ 簡潔的現代寫法
String result = names.stream()
.collect(Collectors.joining(“, “));
Collectors.joining() 的各種用法
- 基本用法 - 只有分隔符
Listfruits = Arrays.asList(“蘋果”, “香蕉”, “橘子”);
// 結果: “蘋果,香蕉,橘子”
String result = fruits.stream()
.collect(Collectors.joining(“,”));
2. 有前綴和後綴
List
// 結果: “[項目1, 項目2, 項目3]”
String result = items.stream()
.collect(Collectors.joining(“, “, “[“, “]”));
3. 搭配 map() 轉換
List
// 拼接使用者名稱
String userNames = users.stream()
.map(User::getName)
.collect(Collectors.joining(“, “));
// 拼接使用者 ID
String userIds = users.stream()
.map(user -> String.valueOf(user.getId()))
.collect(Collectors.joining(“,”));
4. 複雜物件的格式化拼接
List
// 結果: “商品: iPhone($999), 商品: Samsung($799), 商品: Pixel($699)”
String productList = products.stream()
.map(p -> String.format(“商品: %s($%d)”, p.getName(), p.getPrice()))
.collect(Collectors.joining(“, “));
實際應用場景
- 生成 SQL IN 子句
ListuserIds = Arrays.asList(1L, 2L, 3L, 4L);
// ❌ 傳統寫法
StringBuilder inClause = new StringBuilder(“(“);
for (int i = 0; i < userIds.size(); i++) {
if (i > 0) inClause.append(“,”);
inClause.append(userIds.get(i));
}
inClause.append(“)”);
// ✅ 使用 joining()
String inClause = userIds.stream()
.map(String::valueOf)
.collect(Collectors.joining(“,”, “(“, “)”));
String sql = “SELECT * FROM users WHERE id IN “ + inClause;
// 結果: “SELECT * FROM users WHERE id IN (1,2,3,4)”
2. 生成 CSV 格式
List
// 生成 CSV 行
String csvHeader = “姓名,部門,薪資”;
String csvData = employees.stream()
.map(emp -> String.join(“,”,
emp.getName(),
emp.getDepartment(),
String.valueOf(emp.getSalary())))
.collect(Collectors.joining(“\n”));
String fullCsv = csvHeader + “\n” + csvData;
3. 日誌訊息格式化
public void logUserActions(List
String actionSummary = actions.stream()
.map(action -> String.format(“%s在%s執行了%s”,
action.getUserName(),
action.getTimestamp().format(DateTimeFormatter.ofPattern(“HH:mm”)),
action.getActionType()))
.collect(Collectors.joining(“; “));
logger.info("使用者行為摘要: {}", actionSummary);
}
4. HTML 元素生成
List
// 生成 HTML 選單
String htmlMenu = menuItems.stream()
.map(item -> String.format(“
.collect(Collectors.joining(“\n”, “
- \n”, “\n
System.out.println(htmlMenu);
// 輸出:
//
效能考量
- joining() vs StringBuilder
// ✅ joining() 內部已經優化,使用 StringBuilder
ListlargeList = generateLargeStringList();
// 推薦:Collectors.joining() 內部已經優化
String result1 = largeList.stream()
.collect(Collectors.joining(“,”));
// 不推薦:手動 StringBuilder (除非有特殊需求)
StringBuilder sb = new StringBuilder();
largeList.forEach(s -> sb.append(s).append(“,”));
String result2 = sb.toString();
2. 避免重複的 String 操作
// ❌ 效率低下 - 每次 + 都創建新字串
String result = list.stream()
.reduce(“”, (a, b) -> a + “,” + b);
// ✅ 高效 - 內部使用 StringBuilder
String result = list.stream()
.collect(Collectors.joining(“,”));
進階用法
- 條件式拼接
Listitems = Arrays.asList(“”, “有效項目1”, null, “有效項目2”, “”);
String result = items.stream()
.filter(Objects::nonNull)
.filter(s -> !s.trim().isEmpty())
.collect(Collectors.joining(“, “));
// 結果: “有效項目1, 有效項目2”
2. 分組後拼接
List
Map<String, String> departmentEmployees = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.mapping(Employee::getName, Collectors.joining(“, “))
));
// 結果: {“IT”: “張三, 李四”, “HR”: “王五, 趙六”}
3. 多層級拼接
Map<String, List
String categoryList = productsByCategory.entrySet().stream()
.map(entry -> {
String category = entry.getKey();
String products = entry.getValue().stream()
.map(Product::getName)
.collect(Collectors.joining(“, “));
return category + “: “ + products;
})
.collect(Collectors.joining(“\n”));
注意事項
- 處理空值
ListlistWithNulls = Arrays.asList(“A”, null, “B”, null, “C”);
// null 會被轉換為 “null” 字串
String result1 = listWithNulls.stream()
.collect(Collectors.joining(“,”));
// 結果: “A,null,B,null,C”
// 過濾掉 null 值
String result2 = listWithNulls.stream()
.filter(Objects::nonNull)
.collect(Collectors.joining(“,”));
// 結果: “A,B,C”
2. 空集合處理
List
String result = emptyList.stream()
.collect(Collectors.joining(“, “, “[“, “]”));
// 結果: “[]” (前綴和後綴仍會保留)
使用 Collectors.joining() 不僅讓程式碼更簡潔,也更有表達力,同時效能也更好!