使用java 8流转换为大写字母

Phi*_*ila 2 java java-8 java-stream

我有一个像“出租车或公交车司机”这样的字符串列表。我需要将每个单词的第一个字母转换为大写字母,除了单词“or”。有没有简单的方法可以使用Java流来实现这一点。我尝试过使用 Pattern.compile.splitasstream 技术,我无法将所有分割的标记连接回形成原始字符串,任何帮助将不胜感激。如果任何机构需要我可以在此处发布我的代码。

Hol*_*ger 5

您需要正确的模式来标识必须进行更改的位置,当您想要使用 时,需要使用零宽度模式splitAsStream。匹配位置是

\n\n
    \n
  • 一个词开始
  • \n
  • 查看小写字符
  • \n
  • 不看单词 \xe2\x80\x9cor\xe2\x80\x9d
  • \n
\n\n

声明它像\xc2\xa0

\n\n
static final Pattern WORD_START_BUT_NOT_OR = Pattern.compile("\\\\b(?=\\\\p{Ll})(?!or\\\\b)");\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后,使用它来处理令牌就可以通过流和 直接进行map。通过以下方式取回字符串.collect(Collectors.joining())

\n\n
List<String> input  = Arrays.asList("Taxi or bus driver", "apples or oranges");\nList<String> result = input.stream()\n    .map(s -> WORD_START_BUT_NOT_OR.splitAsStream(s)\n        .map(w -> Character.toUpperCase(w.charAt(0))+w.substring(1))\n        .collect(Collectors.joining()))\n    .collect(Collectors.toList());\nresult.forEach(System.out::println);\n
Run Code Online (Sandbox Code Playgroud)\n\n
static final Pattern WORD_START_BUT_NOT_OR = Pattern.compile("\\\\b(?=\\\\p{Ll})(?!or\\\\b)");\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,拆分时,总会有第一个令牌,无论它是否符合条件。由于单词 \xe2\x80\x9cor\xe2\x80\x9d 通常不会出现在短语的开头,并且转换对于非小写字母字符是透明的,因此这在这里应该不是问题。否则,用流特殊处理第一个元素会使代码过于复杂。如果 \xe2\x80\x99 是一个问题,那么循环会更好。

\n\n

基于循环的解决方案可能看起来像

\n\n
private static final Pattern FIRST_WORD_CHAR_BUT_NOT_OR\n                           = Pattern.compile("\\\\b(?!or\\\\b)\\\\p{Ll}");\n
Run Code Online (Sandbox Code Playgroud)\n\n

(现在使用与字符匹配的模式而不是查看它)

\n\n
public static String capitalizeWords(String phrase) {\n    Matcher m = FIRST_WORD_CHAR_BUT_NOT_OR.matcher(phrase);\n    if(!m.find()) return phrase;\n    StringBuffer sb = new StringBuffer();\n    do m.appendReplacement(sb, m.group().toUpperCase()); while(m.find());\n    return m.appendTail(sb).toString();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

作为奖励,它还能够处理跨越多个char单元的字符。从Java\xc2\xa09开始,StringBuffer可以替换为StringBuilder以提高效率。这个方法可以像这样使用

\n\n
List<String> result = input.stream()\n    .map(s -> capitalizeWords(s))\n    .collect(Collectors.toList());\n
Run Code Online (Sandbox Code Playgroud)\n\n

也可以将 lambda 表达式替换s -> capitalizeWords(s)为以下形式的方法引用。ContainingClass::capitalizeWords

\n