Bir Java dizesini tüm büyük harflerden (alt çizgilerle ayrılmış kelimeler) CamelCase'e (kelime ayırıcıları olmadan) dönüştürmenin en basit yolu nedir?


152

Başlık hemen hemen her şeyi söylüyor. Java'da "THIS_IS_AN_EXAMPLE_STRING"biçimden " ThisIsAnExampleString" biçimine bir dize dönüştürebilmemin en basit / en zarif yolu nedir? Bunu yapmak için en az bir yol String.replaceAll()ve bir normal ifade olmalı .

İlk düşüncelerim: dizeyi bir alt çizgi ( _) ile başa döndür, tüm dizeyi küçük harfe dönüştür ve sonra alt çizgi sürümünden önce bir alt çizgi ile gelen her karakteri dönüştürmek için replaceAll komutunu kullan.


12
Editörün notu, 2015-03: yukarıdaki "ilk düşünceler" süper aptal. Altı yıl içinde yazılım geliştirme hakkında çok şey öğreniyorsunuz.
Matt Ball

4
'Bunu ne salak yazdı' diye sorduğunuzda ve yaptığınız genç, aptalı bulmak için kaynak kontrolüne bakın. Orada bulundum, bitti.
pierus

@MattBall: Ben ilk düşünceler sürümünü seviyorum, bir kütüphane gerektirmez ve sadece bir dize birleştirme ve iki regex değiştirilmesi gerekir.
Konrad Höffner

Yanıtlar:


192

Başka bir seçenek de Google Guava'nın com.google.common.base.CaseFormat

George Hawkins bu kullanım örneğiyle bir yorum yaptı:

CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "THIS_IS_AN_EXAMPLE_STRING");

3
Örnek için George Hawkins'in [kullanıcı: 245602] açıklamasına bakınız. stackoverflow.com/questions/1143951/…
Michael Scheper

5
Android için geliştirirken saf java cevaplarını özlüyorum.
eliocs

1
Bu cevap benim için en faydalı olanı. Kendi kodumu çok iyi yazabilirdim, ama başka biri zaten varsa, kesinlikle tekerleği yeniden keşfetmek istemiyorum.
James Dunn



128

Apache Commons dil kütüphanesindeki WordUtils'e bir göz atın :

Özellikle, capitalizeFully (String str, char [] delimiters) yöntemi işi yapmalıdır:

String blah = "LORD_OF_THE_RINGS";
assertEquals("LordOfTheRings", WordUtils.capitalizeFully(blah, new char[]{'_'}).replaceAll("_", ""));

Yeşil çubuk!


55
Hayır efendim! Bu mevcut, zaten çalışan yardımcı programları kendimiz yeniden yazmalıyız, çünkü uygun programcılarız!
skaffman

24
Cuma öğleden sonra saat 16:42. Herkesin yeniden yazmasına izin vereceğim, bir bira için çıkıyorum \ o /;)
Dan Gravell

1
Daha da önemlisi, mevcut kurulumumla belirli bir pakete bile erişemiyorum ve capitalizeFully yönteminin ötesinde bir şeye gerçekten ihtiyacım olmadığından, kendim yazarak hiçbir şey kaybetmiyorum.
Matt Ball

7
Kararınıza saygı duyuyorum Matt, muhtemelen pozisyonunuzda yapılacak doğru şey. Ancak, aşağıdakileri göz önünde bulundurun: * Ekibinizdeki bir başkası, harfleri değiştirmek için bir rutine ihtiyaçları olduğuna karar verir. Uygularlar. Artık bakım yapmak için ~ 20 satırınız var. Kütüphaneyi kullansaydınız ~ 2 olurdu. Ve birim testlerini de unutmayın! * Kabul edilen yanıtın, yöntem adının kodun ne yaptığını açıklamaması açısından bir dezavantajı vardır. Müşterekler gibi iyi kullanılmış bir API nadiren bu dezavantajlara sahiptir. Mesele şu ki, bakım en büyük yazılım maliyeti. Genellikle yeniden kullanım iyi bir fikirdir.
Dan Gravell

2
"Bu pakete erişmek" için repo1.maven.org/maven2/commons-lang/commons-lang/2.5/… ' yi sınıf yolunuza bırakın . Maven eseri commons-lang: commons-lang: 2.5 ve Maven Central'dan kolayca elde edilebilir.
Hendy Irawan

90
static String toCamelCase(String s){
   String[] parts = s.split("_");
   String camelCaseString = "";
   for (String part : parts){
      camelCaseString = camelCaseString + toProperCase(part);
   }
   return camelCaseString;
}

static String toProperCase(String s) {
    return s.substring(0, 1).toUpperCase() +
               s.substring(1).toLowerCase();
}

Not : Bağımsız değişken doğrulaması eklemeniz gerekir.


1
Güzel bir yanıt, ancak yöntem adı ya dizenin bölündüğünü ya da mantığın dışsallaştırıldığını ve yöntem çağrılarının bir boru olarak hizalandığını açıklarsa, örneğin "THIS_IS_AN_EXAMPLE_STRING" .removeUnderscores (). ToCamelCase () Bu biraz daha iyi olurdu. daha çok kullanılabilir.
Dan Gravell

1
Bu mutlaka daha iyi değildir (evet olsa da, daha fazla kullanılabilir). İsim biçimlendirme kurallarına gelince, deve çantası alt çizgi kullanmamak anlamına gelebilir; madalyonun ters tarafında, alt çizgi kullanmayı belirten kurallar vardır. Yani bence, bu sadece bir formattan diğerine dönüştürmek için bir yöntem.
Matt Ball

58
Google guava kütüphanesi, ortak sözleşmeler arasında dönüşüm yapmak için daha genel bir yardımcı program numarasına sahiptir. Bu durumda yapardın String result = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "THIS_IS_AN_EXAMPLE_STRING");. Bkz. Com.google.common.base.CaseFormat javadoc .
George Hawkins

1
Bu yanıt, Türkçe gibi yerel ayarlarda kullanıldığında sorunlara yol açacaktır ... Kodunuz birden fazla yerel ayarda kullanılacaksa, varsayılan yerel ayara bağlı olanları değil, toUpperCase (Locale) ve toLowercase (Locale) komutlarını kullanın.
vkraemer

2
@DanGravell: alt çizgileri kaldırdığınızda, sözcükleri ayırt etmek artık mümkün değildir.
njzk2

18

Apache Commons ile Lang3 lib çok kolay.

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;

public String getName(String text) {
  return StringUtils.remove(WordUtils.capitalizeFully(text, '_'), "_");
}

Misal:

getName("SOME_CONSTANT");

verir:

"SomeConstant"

2
Değişken adı durumunda, ad geçerli değildir, çünkü ad küçük harfle başlamalıdır.
Seby

9
public static void main(String[] args) {
    String start = "THIS_IS_A_TEST";
    StringBuffer sb = new StringBuffer();
    for (String s : start.split("_")) {
        sb.append(Character.toUpperCase(s.charAt(0)));
        if (s.length() > 1) {
            sb.append(s.substring(1, s.length()).toLowerCase());
        }
    }
    System.out.println(sb);
}

3
gerekli değil s.length testi
njzk2 9:13

9

İşte size yardımcı olabilecek bir kod snippet'i:

String input = "ABC_DEF";
StringBuilder sb = new StringBuilder();
for( String oneString : input.toLowerCase().split("_") )
{
    sb.append( oneString.substring(0,1).toUpperCase() );
    sb.append( oneString.substring(1) );
}

// sb now holds your desired String

Bu çözüm ALL_UPPER - Deve davası için uygundur. Ancak programdaki küçük bir değişiklik de MixED_case veya lower_case (yılan örneği) ile başa çıkabilir. İzin veriliyorsa bir düzenleme önerdim.
sud007

6

Akışları kullanan Java 1.8 örneği

String text = "THIS_IS_SOME_TEXT";

String bactrianCamel = Stream.of(text.split("[^a-zA-Z0-9]"))
        .map(v -> v.substring(0, 1).toUpperCase() + v.substring(1).toLowerCase())
        .collect(Collectors.joining());
String dromedaryCamel = bactrianCamel.toLowerCase().substring(0, 1) + bactrianCamel.substring(1); 

System.out.printf("%s is now %s%n", text, dromedaryCamel); 

THIS_IS_SOME_TEXT şimdi bu


Bu yanıtı seviyorum, ancak giriş dizesi zaten deve durumunda, bu durumda tüm giriş küçük harflerle bir kusur var. örneğin abcDef abcdef olur.
mrswadge

text.matches( "([a-z]+[a-zA-Z0-9]+)+" )Deve gövdesinden önce yapılan bir test , muhtemelen alt gövde sorunu için makul bir çözümdür.
mrswadge

2

Emin değilim, ama daha az bellek kullanabileceğimi ve char-by-char yaparak güvenilir performans elde edebileceğimi düşünüyorum. Ben benzer bir şey yapıyordum, ama arka plan iş parçacıkları döngüler, bu yüzden şimdilik bu çalışıyorum. String.split beklenenden daha pahalı olma ile bazı deneyim yaşadım. Ve Android üzerinde çalışıyorum ve GC hıçkırıklarının cpu kullanımından daha fazla bir sorun olmasını bekliyorum.

  public static String toCamelCase(String value) {
    StringBuilder sb = new StringBuilder();

    final char delimChar = '_';
    boolean lower = false;
    for (int charInd = 0; charInd < value.length(); ++charInd) {
      final char valueChar = value.charAt(charInd);
      if (valueChar == delimChar) {
        lower = false;
      } else if (lower) {
        sb.append(Character.toLowerCase(valueChar));
      } else {
        sb.append(Character.toUpperCase(valueChar));
        lower = true;
      }
    }

    return sb.toString();
  }

String.split'in pahalı olduğu bir ipucu, girdisinin bir regex (String.indexOf gibi bir karakter değil) olması ve bir dizi döndürmesi (döngü bir kerede yalnızca bir şey kullandığından bir yineleyici yerine) döndürmesidir. Ayrıca "AB_AB_AB_AB_AB_AB ..." gibi vakalar herhangi bir toplu kopyanın verimliliğini bozar ve uzun dizeler için girdi dizesinden daha fazla bellek kullanır.

Oysa karakterlerin arasında döngü yapmanın kanonik bir durumu yoktur. Bu yüzden benim için gereksiz bir normal ifade ve dizinin yükü genellikle daha az tercih edilir gibi görünüyor (daha sonra olası toplu kopya verimliliğinden vazgeçmek). Fikirleri / düzeltmeleri duymak, teşekkürler.


2
public String withChars(String inputa) {
    String input = inputa.toLowerCase();
    StringBuilder sb = new StringBuilder();
    final char delim = '_';
    char value;
    boolean capitalize = false;
    for (int i=0; i<input.length(); ++i) {
        value = input.charAt(i);
        if (value == delim) {
            capitalize = true;
        }
        else if (capitalize) {
            sb.append(Character.toUpperCase(value));
            capitalize = false;
        }
        else {
            sb.append(value);
        }
    }

    return sb.toString();
}

public String withRegex(String inputa) {
    String input = inputa.toLowerCase();
    String[] parts = input.split("_");
    StringBuilder sb = new StringBuilder();
    sb.append(parts[0]);
    for (int i=1; i<parts.length; ++i) {
        sb.append(parts[i].substring(0,1).toUpperCase());
        sb.append(parts[i].substring(1));
    }

    return sb.toString();
}

Times: mili saniye olarak.

Iterations = 1000
WithChars: start = 1379685214671 end = 1379685214683 diff = 12
WithRegex: start = 1379685214683 end = 1379685214712 diff = 29

Iterations = 1000
WithChars: start = 1379685217033 end = 1379685217045 diff = 12
WithRegex: start = 1379685217045 end = 1379685217077 diff = 32

Iterations = 1000
WithChars: start = 1379685218643 end = 1379685218654 diff = 11
WithRegex: start = 1379685218655 end = 1379685218684 diff = 29

Iterations = 1000000
WithChars: start = 1379685232767 end = 1379685232968 diff = 201
WithRegex: start = 1379685232968 end = 1379685233649 diff = 681

Iterations = 1000000
WithChars: start = 1379685237220 end = 1379685237419 diff = 199
WithRegex: start = 1379685237419 end = 1379685238088 diff = 669

Iterations = 1000000
WithChars: start = 1379685239690 end = 1379685239889 diff = 199
WithRegex: start = 1379685239890 end = 1379685240585 diff = 695

Iterations = 1000000000
WithChars: start = 1379685267523 end = 1379685397604 diff = 130081
WithRegex: start = 1379685397605 end = 1379685850582 diff = 452977

Harika, "THIS_IS_AN_EXAMPLE_STRING" girişi ile yineleniyor mu?
leorleor

@leorleor Iteration = 1000000000 WithChars: başlangıç ​​= 1387547394726 end = 1387547889896 diff = 495170 WithRegex: başlangıç ​​= 1387547889897 end = 1387548944739 fark = 1054842
Srisa 14:13

1

Org.modeshape.common.text.Inflector kullanabilirsiniz .

özellikle:

String camelCase(String lowerCaseAndUnderscoredWord,
    boolean uppercaseFirstLetter, char... delimiterChars) 

Varsayılan olarak, bu yöntem dizeleri UpperCamelCase'e dönüştürür.

Maven artefaktı: org.modeshape: modeshape-ortak: 2.3.0.

JBoss deposunda: https://repository.jboss.org/nexus/content/repositories/releases

İşte JAR dosyası: https://repository.jboss.org/nexus/content/repositories/releases/org/modeshape/modeshape-common/2.3.0.Final/modeshape-common-2.3.0.Final.jar


1

Bunu da deneyebilirsiniz:

 public static String convertToNameCase(String s)
    {
        if (s != null)
        {
            StringBuilder b = new StringBuilder();
            String[] split = s.split(" ");
            for (String srt : split)
            {
                if (srt.length() > 0)
                {
                    b.append(srt.substring(0, 1).toUpperCase()).append(srt.substring(1).toLowerCase()).append(" ");
                }
            }
            return b.toString().trim();
        }
        return s;
    }

1
protected String toCamelCase(String input) {
    if (input == null) {
        return null;
    }

    if (input.length() == 0) {
        return "";
    }

    // lowercase the first character
    String camelCaseStr = input.substring(0, 1).toLowerCase();

    if (input.length() > 1) {
        boolean isStartOfWord = false;

        for (int i = 1; i < input.length(); i++) {
            char currChar = input.charAt(i);
            if (currChar == '_') {
                // new word. ignore underscore
                isStartOfWord = true;
            } else if (Character.isUpperCase(currChar)) {
                // capital letter. if start of word, keep it
                if (isStartOfWord) {
                    camelCaseStr += currChar;
                } else {
                    camelCaseStr += Character.toLowerCase(currChar);
                }
                isStartOfWord = false;
            } else {
                camelCaseStr += currChar;
                isStartOfWord = false;
            }
        }
    }

    return camelCaseStr;
}

1
public String CamelCase(String str)
{
    String CamelCase="";
    String parts[] = str.split("_");
    for(String part:parts)
    {
        String as=part.toLowerCase();
        int a=as.length();
        CamelCase = CamelCase + as.substring(0, 1).toUpperCase()+ as.substring(1,a);    
    }
    return CamelCase;
}

Bu CamelCase dönüştürmek için en basit programdır. size yardımcı olacağını umuyoruz ..


0

Bu dönüştürür Enum ConstantDeve Durumunda içine. Böyle bir işlev arayan herkes için yararlı olacaktır.

public enum TRANSLATE_LANGUAGES {
        ARABIC("ar"), BULGARIAN("bg"), CATALAN("ca"), CHINESE_SIMPLIFIED("zh-CN"), CHINESE_TRADITIONAL("zh-TW"), CZECH("cs"), DANISH("da"), DUTCH("nl"), ENGLISH("en"), ESTONIAN("et"), FINNISH("fi"), FRENCH(
                "fr"), GERMAN("de"), GREEK("el"), HAITIAN_CREOLE("ht"), HEBREW("he"), HINDI("hi"), HMONG_DAW("mww"), HUNGARIAN("hu"), INDONESIAN("id"), ITALIAN("it"), JAPANESE("ja"), KOREAN("ko"), LATVIAN(
                "lv"), LITHUANIAN("lt"), MALAY("ms"), NORWEGIAN("no"), PERSIAN("fa"), POLISH("pl"), PORTUGUESE("pt"), ROMANIAN("ro"), RUSSIAN("ru"), SLOVAK("sk"), SLOVENIAN("sl"), SPANISH("es"), SWEDISH(
                "sv"), THAI("th"), TURKISH("tr"), UKRAINIAN("uk"), URDU("ur"), VIETNAMESE("vi");

        private String code;

        TRANSLATE_LANGUAGES(String language) {
            this.code = language;
        }

        public String langCode() {
            return this.code;
        }

        public String toCamelCase(TRANSLATE_LANGUAGES lang) {
            String toString = lang.toString();
            if (toString.contains("_")) {
                String st = toUpperLowerCase(toString.split("_"));
            }

            return "";
        }

        private String toUpperLowerCase(String[] tempString) {
            StringBuilder builder = new StringBuilder();

            for (String temp : tempString) {

                String char1 = temp.substring(0, 1);
                String restString = temp.substring(1, temp.length()).toLowerCase();
                builder.append(char1).append(restString).append(" ");

            }

            return builder.toString();
        }
    }

0

Buna bir çözüm daha aşağıdaki gibi olabilir.

public static String toCamelCase(String str, String... separators) {
    String separatorsRegex = "\\".concat(org.apache.commons.lang3.StringUtils.join(separators, "|\\"));
    List splits = Arrays.asList(str.toLowerCase().split(separatorsRegex));
    String capitalizedString = (String)splits.stream().map(WordUtils::capitalize).reduce("", String::concat);
    return capitalizedString.substring(0, 1).toLowerCase() + capitalizedString.substring(1);
}

0
public static final String  UPPER_CAMEL = "initUp";
public static final String  LOWER_CAMEL = "initLow";

public String toCamel(String src, String separator, String format) {
    StringBuilder builder = new StringBuilder(src.toLowerCase());
    int len = builder.length();

    for (int idx = builder.indexOf(separator); idx > 0 && idx < len; idx = builder.indexOf(separator, idx)) {
        builder = builder.replace(idx, idx + 2, (String.valueOf(builder.charAt(idx + 1)).toUpperCase()));
    }

    switch (format) {
    case LOWER_CAMEL:
        builder.setCharAt(0, Character.toLowerCase(builder.charAt(0)));
        break;
    default:
        builder.setCharAt(0, Character.toUpperCase(builder.charAt(0)));
        break;
    }

    return builder.toString();

}

Olarak çağırma

toCamel("THIS_IS_AN_EXAMPLE_STRING", "_", UPPER_CAMEL)

Yürütme Süresi: 14 ms


0

Basit bir snnipet:

 public static String camelCase(String in) {
    if (in == null || in.length() < 1) { return ""; } //validate in
    String out = "";
    for (String part : in.toLowerCase().split("_")) {
        if (part.length() < 1) { //validate length
            continue;
        }
        out += part.substring(0, 1).toUpperCase();
        if (part.length() > 1) { //validate length
            out += part.substring(1);
        }
    }
    return out;
}

-2

Birden çok dize için Java 8:

import com.google.common.base.CaseFormat;



String camelStrings = "YOUR_UPPER, YOUR_TURN, ALT_TAB";

List<String> camelList = Arrays.asList(camelStrings.split(","));
camelList.stream().forEach(i -> System.out.println(CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, i) + ", "));

1
Yinelenen cevap
Mark Jeronimus

-2
    protected String toCamelCase(CaseFormat caseFormat, String... words){
        if (words.length  == 0){
          throw new IllegalArgumentException("Word list is empty!");
        }

        String firstWord = words[0];
        String [] restOfWords = Arrays.copyOfRange(words, 1, words.length);

        StringBuffer buffer = new StringBuffer();
        buffer.append(firstWord);
        Arrays.asList(restOfWords).stream().forEach(w->buffer.append("_"+ w.toUpperCase()));

        return CaseFormat.UPPER_UNDERSCORE.to(caseFormat, buffer.toString());

    }

1
CaseFormatstandart API değildir. Guava ise yinelenen cevap.
Mark Jeronimus
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.