有没有一种将字符串转换为标题格式的方法?

126
有没有内置的方法可以将一个字符串转换为标题格式?

7
阅读此问题的每个人:请注意这里得票最高的许多答案并不适用于所有语言。您需要一个具有i18n意识的库进行正确的标题大小写转换,比如ICU4J(请参见Daniel F的答案)。 - sffc
这个回答解决了你的问题吗?如何将字符串中每个单词的首字母大写 - M. Justin
我撤回我的重复问题。这个问题特意不使用标题大小写,即保留每个单词非首字母的大小写,而不是将它们改为大写。例如,aBcD -> "ABcD",而不是"Abcd"。 - M. Justin
22个回答

129

19
WordUtils.capitalizeFully() 对我而言更好,因为它给出了以下结果: WordUtils.capitalizeFully("i am FINE") = "I Am Fine" - theINtoy
3
一个小更新,WordUtils已经转移到Commons Text中,并且在Commons Lang中已被弃用。 - msrd0
2
Spring也有StringUtils.capitalise() - OrangeDog
@OrangeDog,您是指capitalize()方法吗? - TylerH
1
2021年:Apache Commons中的WordUtils现已被弃用。请使用StringUtils。 - singh.rbir

66

Java的String类中没有capitalize()或titleCase()方法。你有两个选择:

 StringUtils.capitalize(null)  = null
 StringUtils.capitalize("")    = ""
 StringUtils.capitalize("cat") = "Cat"
 StringUtils.capitalize("cAt") = "CAt"
 StringUtils.capitalize("'cat'") = "'cat'"
  • 编写(又一个)静态帮助方法 toTitleCase()

示例实现

public static String toTitleCase(String input) {
    StringBuilder titleCase = new StringBuilder(input.length());
    boolean nextTitleCase = true;

    for (char c : input.toCharArray()) {
        if (Character.isSpaceChar(c)) {
            nextTitleCase = true;
        } else if (nextTitleCase) {
            c = Character.toTitleCase(c);
            nextTitleCase = false;
        }

        titleCase.append(c);
    }

    return titleCase.toString();
}

测试用例

    System.out.println(toTitleCase("string"));
    System.out.println(toTitleCase("another string"));
    System.out.println(toTitleCase("YET ANOTHER STRING"));

输出:

字符串
另一个字符串
仍然是一个字符串

1
这是一个不错的小例程,但它无法处理字符串可能表示名称的更一般情况。在这种情况下,大写也需要出现在撇号和连字符后面。例如:O'Connor 和 J. Wilkes-Booth。当然,其他语言可能有额外的标题大小写规则。 - scottb
1
如果要包含那个,难道不需要整个字典查找来确定当前单词是否是一个名称吗?对于任何一个方法来说,这似乎有点过分。 - MMJZ
这段代码几乎没问题,因为有些名字可能带有介词,例如de、del、della、dei、da,比如Maria del Carmen、Maria da Silva、Maria della Salute等。http://www.coderanch.com/t/35096/Programming/Extract-lastname-lastname-firstname - Junior Mayhé
1
注意:为避免在 StringBuilder 中使用的内部 char[] 调整大小,建议使用 new StringBuilder(input.length()) - Lino
3
@sproketboy 我的想法是提供一个处理Java命名规范的实现,而不是处理任何表示名称的字符串等。要正确处理所有语言/区域差异以处理名称需要付出更多努力。 - dfa
显示剩余2条评论

43

如果我可以提交我的解决方案...

下面的方法基于dfa发布的方法。它进行了以下重大改变(适用于我当时需要的解决方案):除非紧接着一个“可操作分隔符”,否则它将输入字符串中的所有字符都强制转换为小写,否则该字符将被强制转换为大写。

我的例行程序的一个主要局限性是它假设“首字母大写”在所有语言环境中都有统一定义,并且使用了与我所用相同的大小写约定,因此在这方面它比dfa的代码不那么有用。

public static String toDisplayCase(String s) {

    final String ACTIONABLE_DELIMITERS = " '-/"; // these cause the character following
                                                 // to be capitalized
    
    StringBuilder sb = new StringBuilder();
    boolean capNext = true;

    for (char c : s.toCharArray()) {
        c = (capNext)
                ? Character.toUpperCase(c)
                : Character.toLowerCase(c);
        sb.append(c);
        capNext = (ACTIONABLE_DELIMITERS.indexOf((int) c) >= 0); // explicit cast not needed
    }
    return sb.toString();
}

测试值

a string

maRTin o'maLLEY

john wilkes-booth

YET ANOTHER STRING

输出

A String

Martin O'Malley

John Wilkes-Booth

Yet Another String


不要使用类似lj这样的连字符,它的大写是LJ但标题大小写是Lj。请改用Character.toTitleCase - mihi
@mihi:也无法处理其他特殊规则,例如像McNamara或MacDonald这样的姓氏。 - scottb
但是这些情况本质上无法修复。使用正确的大小写转换函数(根据Unicode规则,titlecase应该用于大写单词,而不是uppercase)可以完成(而且很容易)。 - mihi
这样做会不会也导致 "her's" 变成 "Her'S"? - allicarn
没错。这在姓名字段上运作良好,但正如你所指出的那样,在一般散文中并不适用。甚至对于所有姓名都不适用,尤其是对于瓦肯人(T'Pau而不是T'pau)。 - scottb

22

使用来自Apache Commons的WordUtils.capitalizeFully()

WordUtils.capitalizeFully(null)        = null
WordUtils.capitalizeFully("")          = ""
WordUtils.capitalizeFully("i am FINE") = "I Am Fine"

1
不错的解决方案!谢谢!但是这并不总是百分之百有效,因为它也会将例如“a”在标题中大写,例如:“This is a Title”。请参见http://english.stackexchange.com/questions/14/which-words-in-a-title-should-be-capitalized。您知道有没有任何处理此问题的库吗? - Eirik W

11

您可以像这样使用 Apache Commons Lang:

WordUtils.capitalizeFully("this is a text to be capitalize")

您可以在此处找到Java文档: WordUtils.capitalizeFully Java文档

如果您想要移除单词之间的空格,您可以使用:

StringUtils.remove(WordUtils.capitalizeFully("this is a text to be capitalize")," ")

你可以在StringUtils.remove的Java文档中找到关于字符串操作的信息。

希望这可以帮到你。


10
如果您想要根据最新的Unicode标准获取正确答案,您应该使用icu4j。
UCharacter.toTitleCase(Locale.US, "hello world", null, 0);

请注意,这是与语言环境相关的。

API文档

实现


还可以查看更新的ICU4J API CaseMap:http://icu-project.org/apiref/icu4j/com/ibm/icu/text/CaseMap.Title.html - sffc
还可在Android API级别24中使用:https://developer.android.com/reference/android/icu/lang/UCharacter.html - sffc
1
我用以下内容进行了测试: “alexander and the terrible, horrible, no good, very bad day, by judith viorst and ray cruz”我期望的结果是: “Alexander and the Terrible, Horrible, No Good, Very Bad Day, by Judith Viorst and Ray Cruz”但实际结果是: “Alexander And The Terrible, Horrible, No Good, Very Bad Day, By Judith Viorst And Ray Cruz”并没有按照预期工作。它只是将短语中的每个单词都大写,与其他内置解决方案相同。 - chomp
@chomp 你想要一个基于人工智能的自然语言处理器。这已经超出了大多数在此提到的库的能力范围,而且我认为这超出了这个问题的范围。“Title Case”意味着将所有单词的首字母大写。 - David Lavender
@DavidLavender 我同意这可能很难实现,但一个是“Title Case”,另一个是“Fully Capitalized”,也许名称有误导,或者至少在我的情况下是这样。 https://zh.wikipedia.org/wiki/%E6%A8%99%E9%A1%8C%E5%A4%A7%E5%B0%8F%E5%86%99 - chomp

8

以下是基于 @dfa 和 @scottb 的回答并处理任何非字母/数字字符的另一种方法:

public final class TitleCase {

    public static String toTitleCase(String input) {

        StringBuilder titleCase = new StringBuilder(input.length());
        boolean nextTitleCase = true;

        for (char c : input.toLowerCase().toCharArray()) {
            if (!Character.isLetterOrDigit(c)) {
                nextTitleCase = true;
            } else if (nextTitleCase) {
                c = Character.toTitleCase(c);
                nextTitleCase = false;
            }
            titleCase.append(c);
        }

        return titleCase.toString();
    }

}

给定输入:

MARY ÄNN O’CONNEŽ-ŠUSLIK

输出为:

Mary Änn O’Connež-Šuslik


3

我写了一个将snake_case转换为lowerCamelCase的程序,但可以根据要求轻松进行调整

private String convertToLowerCamel(String startingText)
{
    String[] parts = startingText.split("_");
    return parts[0].toLowerCase() + Arrays.stream(parts)
                    .skip(1)
                    .map(part -> part.substring(0, 1).toUpperCase() + part.substring(1).toLowerCase())
                    .collect(Collectors.joining());
}

你的答案非常好,但是这个解决方案似乎不能处理单词序列,也许一个if条件就足够了。 - o12d10

3
使用此方法将字符串转换为标题大小写:
static String toTitleCase(String word) {
    return Stream.of(word.split(" "))
            .map(w -> w.toUpperCase().charAt(0) + w.toLowerCase().substring(1))
            .reduce((s, s2) -> s + " " + s2)
            .orElse("");
}

2

使用Spring的StringUtils

org.springframework.util.StringUtils.capitalize(someText);

如果您已经使用Spring框架,那么这个方法可以避免引入另一个框架。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接