AI 输出处理: 大模型返回的结果往往包含多余的空白、转义字符,输出格式不稳定,需要大量的 ETL(提取、转换、加载)过程, 需要清洗、标准化处理来保证数据质量

在 AI 大模型盛行的今天,字符串处理变得比以往任何时候都更加重要:

提示词工程(Prompt Engineering):

• 需要精确构造和格式化输入文本

• 多行提示词需要合理的缩进和格式

• 动态参数需要安全的字符串拼接

AI 输出处理:

• 大模型返回的结果往往包含多余的空白、转义字符

• 输出格式不稳定,需要大量的 ETL(提取、转换、加载)过程

• 需要清洗、标准化处理来保证数据质量

实际场景:

// AI 返回的不稳定输出
String aiResponse = """
        
        {
          "name": "张三",
          "message": "Hello\\nWorld"
        }
        
    """;

// 需要清洗处理
String cleaned = aiResponse
    .strip()                    // 去除多余空白
    .translateEscapes()         // 处理转义字符
    .lines()                    // 逐行处理
    .filter(line -> !line.isBlank())
    .collect(Collectors.joining("\n"));
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

传统开发的痛点

在传统 Java 开发中,字符串处理往往需要:

• 冗长的代码 – 简单操作需要多行代码

• 第三方库 – 依赖 Apache Commons、Guava 等

• 自定义工具方法 – 重复造轮子

• 性能问题 – 多次字符串操作导致性能损耗

现代 Java 的解决方案

现代 Java 通过内置方法解决了这些痛点,让代码更加简洁、高效、可读:

• ✅ 原生支持 – 无需第三方依赖

• ✅ 链式调用 – 流畅的 API 设计

• ✅ 性能优化 – JVM 层面的优化

• ✅ AI 友好 – 完美适配 AI 时代的文本处理需求

核心新方法详解

1. isBlank() – 智能空白检查

引入版本:Java 11

问题:传统的 isEmpty() 只检查长度为 0,无法识别只包含空白字符的字符串。

// 传统方式
String str = "   ";
boolean isEmpty = str.trim().isEmpty(); // 繁琐

// 现代方式
boolean isBlank = str.isBlank(); // 简洁明了
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

应用场景:

  • • 表单验证
  • • 用户输入检查
  • • 配置文件解析

public boolean isValidUsername(String username) {
    return username != null && !username.isBlank();
}
  • 1.
  • 2.
  • 3.

2. lines() – 流式处理多行文本

引入版本:Java 11

问题:处理多行文本需要手动分割和迭代。

String text = """
    第一行
    第二行
    第三行
    """;

// 使用 lines() 流式处理
text.lines()
    .filter(line -> !line.isBlank())
    .map(String::trim)
    .forEach(System.out::println);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

实战案例:日志文件分析

public List<String> extractErrors(String logContent) {
    return logContent.lines()
        .filter(line -> line.contains("ERROR"))
        .collect(Collectors.toList());
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

3. repeat(int count) – 字符串重复

引入版本:Java 11

问题:重复字符串需要循环或 StringBuilder。

// 传统方式
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 3; i++) {
    sb.append("Java");
}
String result = sb.toString();

// 现代方式
String result = "Java".repeat(3); // "JavaJavaJava"
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

应用场景:

• 生成分隔线

• 创建缩进

• 数据填充

public String createSeparator(int length) {
    return "=".repeat(length);
}

public String indent(int level) {
    return "  ".repeat(level);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

4. strip() 系列 – Unicode 感知的空白处理

引入版本:Java 11

关键区别:trim() 只处理 ASCII 空白,strip() 支持所有 Unicode 空白字符。

String str = "  Hello World  ";

str.strip();         // 去除两端空白
str.stripLeading();  // 去除开头空白
str.stripTrailing(); // 去除末尾空白
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

实战对比:

String unicode = "\u2000Hello\u2000"; // Unicode 空格

unicode.trim();   // 无法去除 Unicode 空格
unicode.strip();  // 正确去除
  • 1.
  • 2.
  • 3.
  • 4.

5. indent(int n) – 智能缩进控制

引入版本:Java 12

功能:为每一行添加或移除指定数量的空格。

String code = """
    public void hello() {
        System.out.println("Hello");
    }
    """;

// 增加 4 个空格缩进
String indented = code.indent(4);

// 减少 2 个空格缩进
String dedented = code.indent(-2);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

应用场景:

• 代码生成

• 文档格式化

• JSON/XML 美化

public String formatJson(String json, int indentLevel) {
    return json.lines()
        .map(line -> " ".repeat(indentLevel) + line)
        .collect(Collectors.joining("\n"));
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

6. transform() – 函数式转换

引入版本:Java 12

核心思想:将字符串作为输入,应用函数进行转换。

String result = "hello"
    .transform(String::toUpperCase)
    .transform(s -> s + " WORLD")
    .transform(s -> ">>> " + s);
// 结果: ">>> HELLO WORLD"
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

实战案例:数据清洗管道

public String sanitizeInput(String input) {
    return input
        .transform(String::strip)
        .transform(String::toLowerCase)
        .transform(s -> s.replaceAll("[^a-z0-9]", ""));
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

优势:

• 链式调用更流畅

• 避免中间变量

• 提高代码可读性

7. formatted() – 现代化格式化

引入版本:Java 15(预览),Java 17(正式)

问题:String.format() 是静态方法,不够流畅。

// 传统方式
String message = String.format("Hello, %s! You have %d messages.", name, count);

// 现代方式
String message = "Hello, %s! You have %d messages.".formatted(name, count);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

链式调用示例:

String report = """
    用户: %s
    余额: %.2f
    状态: %s
    """
    .formatted(username, balance, status)
    .transform(String::strip);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

优势:

• 看起来更简洁

• 不会打断链式调用的流程

• 可与 Records 和模板一起使用

8. stripIndent() – 移除附加缩进

引入版本:Java 13(用于文本块),Java 21(公开 API)

功能:移除字符串每一行的公共前导空白,常用于文本块的格式化。

String text = """
        public void hello() {
            System.out.println("Hello");
        }
    """;

// 移除公共缩进
String stripped = text.stripIndent();
System.out.println(stripped);
// 输出:
// public void hello() {
//     System.out.println("Hello");
// }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

应用场景:

• 处理多行代码片段

• 格式化嵌入的 SQL 或 JSON

• 清理文本块的缩进

public String generateSQL() {
    return """
            SELECT id, name, email
            FROM users
            WHERE status = 'active'
            ORDER BY created_at DESC
        """.stripIndent();
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

实战案例:动态代码生成

public String generateMethod(String methodName, String returnType) {
    return """
            public %s %s() {
                // TODO: implement
                return null;
            }
        """.formatted(returnType, methodName)
           .stripIndent();
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

9. translateEscapes() – 转义序列翻译

引入版本:Java 15

功能:将字符串中的转义序列(如 \n、\t)转换为实际的字符。

String escaped = "Hello\\nWorld\\tJava";
String translated = escaped.translateEscapes();

System.out.println(escaped);     // Hello\nWorld\tJava
System.out.println(translated);  // Hello
                                 // World    Java
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

常见转义序列:

• \n – 换行符

• \t – 制表符

• \r – 回车符

• \\ – 反斜杠

• \” – 双引号

• \’ – 单引号

应用场景:

• 处理配置文件中的转义字符

• 解析用户输入的转义序列

• 处理 JSON 字符串

public String processConfigValue(String value) {
    return value
        .strip()
        .translateEscapes();
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

实战案例:AI Json Repair

public class PromptBuilder {
    /**
     * 构建结构化的 AI 提示词
     */
    public String buildPrompt(String role, String task, List<String> examples) {
        String exampleSection = examples.stream()
                .map("- %s"::formatted)
                .collect(Collectors.joining("\n"))
                .indent(2);

        return """
            Role: %s
            
            Task:
            %s
            
            Examples:
            %s
            
            Please provide your response in JSON format.
            """.formatted(role, task.indent(2).strip(), exampleSection)
                .stripIndent();
    }

    /**
     * 清洗 AI 返回的结果
     */
    public String cleanAIResponse(String aiOutput) {
        return aiOutput
                .strip()                           // 去除首尾空白
                .lines()                           // 按行处理
                .map(String::strip)                // 去除每行空白
                .filter(line -> !line.isBlank())   // 过滤空行
                .filter(line -> !line.startsWith("```"))  // 去除代码块标记
                .collect(Collectors.joining("\n"))
                .translateEscapes();               // 处理转义字符
    }

    /**
     * 提取 AI 返回的 JSON 内容
     */
    public String extractJson(String aiResponse) {
        List<String> lines = aiResponse.lines()
                .dropWhile(line -> !line.strip().startsWith("{"))  // 跳到 JSON 开始
                .toList();

        // 找到第一个以 } 结尾的行的索引(包含该行)
        int endIndex = 0;
        for (int i = 0; i < lines.size(); i++) {
            if (lines.get(i).strip().endsWith("}")) {
                endIndex = i + 1;  // +1 是因为 subList 的 toIndex 是排他的
                break;
            }
        }

        return String.join("\n", lines.subList(0, endIndex))
                .transform(this::cleanAIResponse);
    }
}
  • 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.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.

使用示例:

void main() {
    PromptBuilder builder = new PromptBuilder();

    // 1. 构建提示词
    String prompt = builder.buildPrompt(
            "Java Expert",
            "Generate a User entity class with validation",
            List.of(
                    "Include id, name, email fields",
                    "Add Jakarta validation annotations",
                    "Use Lombok annotations"
            )
    );

    System.out.println("=== 发送给 AI 的提示词 ===");
    System.out.println(prompt);

    // 2. 模拟 AI 返回的不规范输出
    String aiResponse = """

        Sure! Here's the code:

        ```java
        {
          "className": "User",
          "fields": "id, name, email"
        }
        ```

        Hope this helps!

    """;

    // 3. 清洗 AI 输出
    String cleaned = builder.cleanAIResponse(aiResponse);
    System.out.println("\n=== 清洗后的结果 ===");
    System.out.println(cleaned);

    // 4. 提取 JSON
    String json = builder.extractJson(aiResponse);
    System.out.println("\n=== 提取的 JSON ===");
    System.out.println(json);
}
  • 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.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.

输出结果:

=== 发送给 AI 的提示词 ===
Role: Java Expert

Task:
  Generate a User entity class with validation

Examples:
  - Include id, name, email fields
  - Add Jakarta validation annotations
  - Use Lombok annotations

Please provide your response in JSON format.

=== 清洗后的结果 ===
Sure! Here's the code:
{
"className": "User",
"fields": "id, name, email"
}
Hope this helps!

=== 提取的 JSON ===
{
"className": "User",
"fields": "id, name, email"
}
  • 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.
  • 26.

最佳实践

推荐做法

// 1. 优先使用新方法
String cleaned = input.strip(); // 而非 trim()

// 2. 链式调用提高可读性
String result = text
    .transform(String::strip)
    .transform(String::toLowerCase);

// 3. 结合 Stream API
List<String> valid = inputs.stream()
    .filter(s -> !s.isBlank())
    .map(String::strip)
    .collect(Collectors.toList());
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

避免的做法

// 1. 不要混用旧方法
String result = text.trim().strip(); // 冗余

// 2. 避免过度链式调用
String bad = text
    .transform(s -> s.strip())
    .transform(s -> s.toLowerCase())
    .transform(s -> s.toUpperCase())
    .transform(s -> s.strip()); // 过度复杂

文章来自:51CTO

Loading

作者 yinhua

发表回复