Java实现标点后大小写与空格处理规则的代码如何修复
字符串大小写与格式调整功能修复方案
需求规则
- 句首或标点符号后首字母大写
- 标点符号后添加空格
- 缩写后的单词首字母无需大写
- 带空格的连字符
-后首字母大写 - 不带空格的连字符
-后首字母不大写
原有问题代码
private static char[] PUNCTUATION_MARKS = { '?', '!', ';', '.', '-' }; applyCorrectCase("step 1 - take your car"); applyCorrectCase("reply-to address"); applyCorrectCase("req. start"); applyCorrectCase("alt. del. date [alternate detection date]"); applyCorrectCase("you are.important for us? to continue?here! yes"); String applyCorrectCase(String value) { String lowerCaseValue = value.toLowerCase(); if (value.contains(". ")) { lowerCaseValue = value.replace(". ", "."); } lowerCaseValue = WordUtils.capitalize(lowerCaseValue, PUNCTUATION_MARKS ); System.out.println(lowerCaseValue.replace(".", ". ")); }
输出对比
实际输出
Step 1 - take your car <--- 此处'-'后的't'需要大写 Reply-To address <--- 此处'-'后的't'需要小写 Req. Start <--- 此处是缩写,'.'后的's'需要小写 Alt. Del. Date [alternate detection date] <--- 此处是缩写,两个'.'后的首字母都需要小写 You are. Important for us? to continue?Here! yes <--- '?'后的't'需要大写,'?'和'H'之间需要加空格,'!'后的'y'需要大写
期望输出
Step 1 - Take your car Reply-to address Req. start Alt. del. date [alternate detection date] You are. Important for us? To continue? Here! Yes
修复思路
原有代码直接使用WordUtils.capitalize无法区分带空格和不带空格的连字符,也无法处理缩写场景,且标点补空格逻辑仅覆盖了句号,导致输出不符合预期。建议放弃依赖工具类的通用规则,改为逐字符遍历自定义规则处理,逻辑如下:
- 先将原始字符串统一转为小写,避免原有大小写干扰
- 遍历每个字符,维护上一个字符的类型状态
- 遇到标点时先补空格,再根据标点类型判断后续字符是否需要大写:
- 如果是不带空格的连字符
-,后续字符保留小写 - 如果是其他标点,需先判断是否属于缩写后缀,缩写后单词首字母强制小写,其余情况后续字符大写
- 如果是不带空格的连字符
修复后代码
import java.util.Arrays; import java.util.HashSet; import java.util.Set; public class CaseFormatter { private static final Set<Character> PUNCTUATIONS = new HashSet<>(Arrays.asList('?', '!', ';', '.')); // 可根据业务需求新增缩写词 private static final Set<String> ABBREVIATIONS = new HashSet<>(Arrays.asList("req.", "alt.", "del.")); public static String applyCorrectCase(String value) { if (value == null || value.isBlank()) { return value; } StringBuilder sb = new StringBuilder(value.toLowerCase()); boolean needCapitalize = true; // 句首默认需要大写 boolean lastIsNoSpaceHyphen = false; for (int i = 0; i < sb.length(); i++) { char c = sb.charAt(i); // 处理连字符逻辑 if (c == '-') { // 判断是否为不带空格的连字符 boolean hasLeftSpace = i > 0 && Character.isWhitespace(sb.charAt(i-1)); boolean hasRightSpace = i < sb.length()-1 && Character.isWhitespace(sb.charAt(i+1)); if (hasLeftSpace && hasRightSpace) { needCapitalize = true; lastIsNoSpaceHyphen = false; } else { needCapitalize = false; lastIsNoSpaceHyphen = true; } continue; } // 处理普通标点 if (PUNCTUATIONS.contains(c)) { // 标点后补空格 if (i < sb.length()-1 && !Character.isWhitespace(sb.charAt(i+1))) { sb.insert(i+1, ' '); } // 判断是否为缩写后缀 boolean isAbbr = false; int wordStart = i - 1; while (wordStart >= 0 && Character.isLetter(sb.charAt(wordStart))) { wordStart--; } if (wordStart < i - 1) { String word = sb.substring(wordStart + 1, i + 1); if (ABBREVIATIONS.contains(word)) { isAbbr = true; } } needCapitalize = !isAbbr; lastIsNoSpaceHyphen = false; continue; } // 处理空格 if (Character.isWhitespace(c)) { if (lastIsNoSpaceHyphen) { needCapitalize = false; } continue; } // 执行大小写转换 if (needCapitalize && Character.isLetter(c)) { sb.setCharAt(i, Character.toUpperCase(c)); needCapitalize = false; } lastIsNoSpaceHyphen = false; } return sb.toString(); } public static void main(String[] args) { System.out.println(applyCorrectCase("step 1 - take your car")); System.out.println(applyCorrectCase("reply-to address")); System.out.println(applyCorrectCase("req. start")); System.out.println(applyCorrectCase("alt. del. date [alternate detection date]")); System.out.println(applyCorrectCase("you are.important for us? to continue?here! yes")); } }
运行上述代码输出完全匹配预期,后续有新增缩写需求,直接添加到ABBREVIATIONS集合即可。
内容的提问来源于stack exchange,提问作者Despotars
相关产品推荐
相关产品推荐

