Apa cara paling sederhana untuk mengonversi string Java dari semua huruf besar (kata-kata dipisahkan oleh garis bawah) ke CamelCase (tanpa pemisah kata)?

152

Judulnya cukup banyak mengatakan itu semua. Apa cara paling sederhana / paling elegan yang dapat saya konversi, di Jawa, string dari format "THIS_IS_AN_EXAMPLE_STRING"ke format " ThisIsAnExampleString"? Saya pikir pasti ada setidaknya satu cara untuk melakukannya menggunakan String.replaceAll()dan regex.

Pikiran awal saya adalah: menambahkan string dengan garis bawah ( _), mengonversi seluruh string menjadi huruf kecil, dan kemudian gunakan replaceAll untuk mengonversi setiap karakter yang diawali dengan garis bawah dengan versi huruf besarnya.

Matt Ball
sumber
12
Catatan Editor, 2015-03: "pemikiran awal" di atas sangat bodoh. Anda belajar banyak tentang membangun perangkat lunak dalam enam tahun.
Matt Ball
4
Saat itu ketika Anda bertanya 'orang bodoh apa yang menulis ini' dan mencari dalam kendali sumber untuk menemukan yang muda, bodoh Anda lakukan. Pernah ke sana, melakukan itu.
pierus
@MattBall: Saya suka versi pemikiran awal, tidak memerlukan pustaka dan hanya membutuhkan rangkaian string dan dua penggantian regex.
Konrad Höffner

Jawaban:

192

Pilihan lain adalah menggunakan Google Guava's com.google.common.base.CaseFormat

George Hawkins meninggalkan komentar dengan contoh penggunaan ini:

CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "THIS_IS_AN_EXAMPLE_STRING");
Arnout Engelen
sumber
3
Lihat komentar oleh George Hawkins [pengguna: 245602] untuk contoh. stackoverflow.com/questions/1143951/…
Michael Scheper
5
Saya kehilangan jawaban java murni karena saya sedang mengembangkan untuk Android.
eliocs
1
Jawaban ini adalah yang paling berguna bagi saya. Saya bisa menulis kode sendiri dengan sangat baik, tetapi jika orang lain sudah memilikinya, saya tentu tidak ingin menemukan kembali kemudi.
James Dunn
1
@ CléssioMendes sudahkah Anda mempertimbangkan untuk mengangkat ini di github.com/google/guava/issues ?
Arnout Engelen
128

Lihatlah WordUtils di perpustakaan lang Apache Commons :

Secara khusus, metode capitalizeFully (String str, char []) harus melakukan pekerjaan:

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

Bar hijau!

Dan Gravell
sumber
55
Tidak pak! Kita harus menulis ulang sendiri utilitas yang sudah ada dan sudah berfungsi ini, karena kita adalah programmer yang tepat!
skaffman
24
Ini 16:42 pada hari Jumat sore. Saya akan membiarkan semua orang menulis ulang, saya keluar untuk minum bir \ o /;)
Dan Gravell
1
Lebih penting lagi, saya bahkan tidak memiliki akses ke paket tertentu dengan pengaturan saya saat ini, dan karena saya benar-benar tidak (belum) membutuhkan sesuatu di luar metode capitalizeFully, saya tidak kehilangan apa-apa dengan menulisnya sendiri.
Matt Ball
7
Saya menghormati keputusan Anda, Matt, mungkin itu hal yang tepat untuk dilakukan di posisi Anda. Namun, pertimbangkan hal-hal berikut: * Orang lain di tim Anda memutuskan mereka perlu rutin untuk bertukar huruf. Mereka menerapkannya. Anda sekarang memiliki ~ 20 baris untuk dipertahankan. Anda akan memiliki ~ 2 jika Anda menggunakan perpustakaan. Dan jangan lupa tes unit! * Jawaban yang diterima memiliki kelemahan karena nama metode tidak menjelaskan apa yang dikerjakan kode. API yang digunakan kembali dengan baik seperti barang umum jarang memiliki kelemahan tersebut. Intinya adalah pemeliharaan adalah biaya perangkat lunak terbesar. Secara umum, menggunakan kembali adalah ide yang bagus.
Dan Gravell
2
Untuk "mengakses paket khusus ini", masukkan repo1.maven.org/maven2/commons-lang/commons-lang/2.5/… ke classpath Anda. Artefak Maven adalah commons-lang: commons-lang: 2.5 dan sudah tersedia dari Maven Central.
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();
}

Catatan : Anda perlu menambahkan validasi argumen.

C. Ross
sumber
1
Jawaban yang bagus, tetapi akan sedikit lebih baik jika nama metode menggambarkan fakta bahwa string terpecah atau logika itu di-eksternalisasi dan panggilan metode disejajarkan sebagai pipa, misalnya "THIS_IS_AN_EXAMPLE_STRING" .removeUnderscores (). ToCamelCase () This lebih dapat digunakan kembali.
Dan Gravell
1
Itu belum tentu lebih baik (meskipun ya, itu lebih dapat digunakan kembali). Ketika datang ke nama konvensi pemformatan, camelcase dapat / tidak menyiratkan tidak menggunakan garis bawah; di sisi sebaliknya dari koin, ada konvensi yang menentukan menggunakan garis bawah. Jadi dalam pikiran saya, ini hanyalah metode untuk mengkonversi dari satu format ke format lainnya.
Matt Ball
58
Perpustakaan Google jambu biji memiliki enum utilitas yang lebih umum untuk mengkonversi antara konvensi umum. Untuk hal ini yang akan Anda lakukan String result = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "THIS_IS_AN_EXAMPLE_STRING");. Lihat com.google.common.base.CaseFormat javadoc .
George Hawkins
1
Jawaban ini akan mengalami masalah ketika digunakan di lokal seperti Turki ... Jika kode Anda akan digunakan di beberapa lokal, gunakan toUpperCase (Lokal) dan toLowercase (Lokal) .. bukan yang bergantung pada lokal default.
vkraemer
2
@DanGravell: sekali Anda menghapus garis bawah, tidak mungkin lagi untuk membedakan kata-kata.
njzk2
18

Dengan Apache Commons Lang3 lib sangat mudah.

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

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

Contoh:

getName("SOME_CONSTANT");

Memberi:

"SomeConstant"
librucha
sumber
2
Dalam hal nama variabel, ini tidak valid karena nama harus dimulai dengan huruf kecil.
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);
}
Yishai
sumber
3
tes s.length tidak diperlukan
njzk2
9

Berikut ini cuplikan kode yang mungkin membantu:

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
Alex B
sumber
Solusi ini sesuai untuk ALL_UPPER ke Kasing camel. Tetapi sedikit perubahan dalam program ini juga dapat menangani MixED_case atau lower_case (kasus ular). Saya telah menyarankan hasil edit jika diizinkan.
sud007
6

Java 1.8 contohnya menggunakan Streams

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 sekarang thisIsSomeText

Mike
sumber
Saya suka jawaban ini, tetapi memiliki cacat jika string input sudah dalam kasus unta, dalam hal ini kasus huruf kecil seluruh input. mis. abcDef menjadi abcdef.
mrswadge
Tes menggunakan text.matches( "([a-z]+[a-zA-Z0-9]+)+" )sebelum unta casing mungkin merupakan solusi yang masuk akal untuk masalah casing rendah.
mrswadge
2

Tidak yakin, tapi saya pikir saya bisa menggunakan lebih sedikit memori dan mendapatkan kinerja yang dapat diandalkan dengan melakukannya char-by-char. Saya melakukan sesuatu yang serupa, tetapi di loop di utas latar belakang, jadi saya mencoba ini untuk saat ini. Saya sudah memiliki pengalaman dengan String.split menjadi lebih mahal dari yang diharapkan. Dan saya sedang bekerja di Android dan berharap cegukan GC lebih menjadi masalah daripada penggunaan cpu.

  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();
  }

Petunjuk bahwa String.split mahal adalah inputnya adalah regex (bukan char seperti String.indexOf) dan mengembalikan array (alih-alih mengatakan iterator karena loop hanya menggunakan satu hal pada satu waktu). Ditambah kasus seperti "AB_AB_AB_AB_AB_AB ..." memecah efisiensi dari salinan massal, dan untuk string panjang menggunakan urutan besarnya lebih banyak memori daripada string input.

Sedangkan perulangan melalui karakter tidak memiliki kasus kanonik. Jadi bagi saya overhead dari regex dan array yang tidak dibutuhkan tampaknya umumnya kurang disukai (kemudian memberikan efisiensi salinan massal). Tertarik untuk mendengar pendapat / koreksi, terima kasih.

Leorleor
sumber
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();
}

Waktu: dalam mili detik.

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
Srisa
sumber
Keren, apakah iterasi dengan input "THIS_IS_AN_EXAMPLE_STRING"?
leorleor
@leorleor Iteration = 1000000000 WithChars: start = 1387547394726 end = 1387547889896 diff = 495170 WithRegex: start = 1387547889897 end = 1387548944739 diff = 1054842
Srisa
1

Anda dapat menggunakan org.modeshape.common.text.Inflector .

Secara khusus:

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

Secara default, metode ini mengubah string menjadi UpperCamelCase.

Artefak Maven adalah: org.modeshape: modeshape-common: 2.3.0.Final

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

Ini file JAR: https://repository.jboss.org/nexus/content/repositories/releases/org/modeshape/modeshape-common/2.3.0.Final/modeshape-common-2.3.0.Final.jar

Hendy Irawan
sumber
1

Anda dapat Coba ini juga:

 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;
    }
Ashish
sumber
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;
}
Muzikant
sumber
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;
}

Ini adalah Program Sederhana untuk dikonversi ke CamelCase. berharap ini Akan Membantu Anda ..

XORG_99
sumber
0

Ini akan dikonversi Enum Constantmenjadi Camel Case. Akan sangat membantu bagi siapa saja yang mencari kesungguhan itu.

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();
        }
    }
AZ_
sumber
0

Satu lagi solusi untuk ini adalah sebagai berikut.

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);
}
Sajani
sumber
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();

}

Doa sebagai

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

Waktu Eksekusi: 14 ms

Arindam
sumber
0

Sebuah snnipet sederhana:

 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;
}
fitorec
sumber
-2

Java 8 untuk beberapa string:

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) + ", "));
DET66
sumber
1
Jawaban
rangkap
-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());

    }
Vladimir
sumber
1
CaseFormatbukan API standar. Jawaban rangkap jika itu jambu biji.
Mark Jeronimus