วิธีที่ง่ายที่สุดในการแปลงสตริง Java จากตัวพิมพ์ใหญ่ทั้งหมด (คำที่คั่นด้วยเครื่องหมายขีดล่าง) เป็น CamelCase (ไม่มีตัวคั่นคำ) คืออะไร?


152

ชื่อค่อนข้างบอกว่ามันทั้งหมด วิธีที่ง่ายที่สุด / หรูหราที่สุดที่ฉันสามารถแปลงได้ใน Java คือสตริงจากรูปแบบ"THIS_IS_AN_EXAMPLE_STRING"เป็นรูปแบบ " ThisIsAnExampleString" ฉันคิดว่าต้องมีอย่างน้อยหนึ่งวิธีในการใช้String.replaceAll()และ regex

ความคิดเริ่มต้นของฉันคือ: เติมสตริงด้วยเครื่องหมายขีดล่าง ( _) แปลงสตริงทั้งหมดเป็นตัวพิมพ์เล็กแล้วใช้ replaceAll เพื่อแปลงอักขระทุกตัวที่นำหน้าด้วยเครื่องหมายขีดล่างด้วยตัวพิมพ์ใหญ่


12
หมายเหตุจากบรรณาธิการ, 2015-03: "ความคิดเริ่มต้น" ด้านบนนั้นโง่มาก คุณเรียนรู้มากมายเกี่ยวกับการสร้างซอฟต์แวร์ในหกปี
Matt Ball

4
ช่วงเวลานั้นเมื่อคุณถามว่า 'คนงี่เง่าที่เขียนสิ่งนี้' และมองในการควบคุมแหล่งที่จะพบว่าเด็กที่โง่ที่คุณทำ เคยทำมาแล้ว
pierus

@ MattBall: ฉันชอบรุ่นความคิดเริ่มต้นมันไม่จำเป็นต้องมีห้องสมุดและเพียงแค่ต้องมีการต่อกันสตริงและสองทดแทน regex
Konrad Höffner

คำตอบ:


192

อีกตัวเลือกหนึ่งคือการใช้ Google Guava com.google.common.base.CaseFormat

George Hawkinsแสดงความคิดเห็นด้วยตัวอย่างการใช้งานนี้:

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

3
อ้างถึงความคิดเห็นโดย George Hawkins [ผู้ใช้: 245602] สำหรับตัวอย่าง stackoverflow.com/questions/1143951/…
Michael Scheper

5
ฉันคิดถึงคำตอบจาวาบริสุทธิ์ขณะที่ฉันพัฒนาสำหรับ Android
eliocs

1
คำตอบนี้มีประโยชน์มากที่สุดสำหรับฉัน ฉันสามารถเขียนรหัสของตัวเองได้เป็นอย่างดี แต่ถ้ามีคนอื่นอยู่แล้วฉันไม่ต้องการที่จะประดิษฐ์ล้อ
James Dunn

อ้างถึงstackoverflow.com/questions/10310321/ … นอกจากนี้
Hartmut P.

1
@ CléssioMendesคุณคิดว่าจะนำสิ่งนี้มาที่github.com/google/guava/issuesหรือไม่?
Arnout Engelen

128

ดูWordUtils ในไลบรารีApache Commons lang :

เมธอด capitalizeFully (String str, char []) ควรทำงาน:

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

แถบสีเขียว!


55
ไม่ครับท่าน! เราควรเขียนยูทิลิตี้ที่มีอยู่และใช้งานได้แล้วเหล่านี้ใหม่สำหรับเราเพราะเป็นโปรแกรมเมอร์ที่เหมาะสม!
skaffman

24
เวลา 16:42 น. ในบ่ายวันศุกร์ ฉันจะให้คนอื่นเขียนมันฉันจะออกสำหรับเบียร์ \ o /;)
แดน Gravell

1
นอกจากนี้ฉันยังไม่สามารถเข้าถึงแพ็คเกจนั้นด้วยการตั้งค่าปัจจุบันของฉันและเนื่องจากฉันไม่ต้องการอะไรเลยนอกจากวิธีการพิมพ์ใหญ่อย่างเต็มที่ฉันจึงไม่เสียอะไรเลยโดยการเขียนด้วยตนเอง
Matt Ball

7
ฉันเคารพการตัดสินใจของคุณแมตต์มันอาจเป็นสิ่งที่ถูกต้องที่จะทำในตำแหน่งของคุณ อย่างไรก็ตามให้พิจารณาสิ่งต่อไปนี้: * มีคนอื่นในทีมของคุณตัดสินใจว่าพวกเขาต้องการกิจวัตรเพื่อสลับตัวพิมพ์และตัวอักษร พวกเขาใช้มัน ตอนนี้คุณมี ~ 20 บรรทัดในการรักษา คุณจะมี ~ 2 ถ้าคุณใช้ห้องสมุด และอย่าลืมทดสอบหน่วย! * คำตอบที่ยอมรับนั้นมีข้อเสียคือชื่อวิธีการไม่ได้อธิบายถึงรหัสที่ใช้ API ที่นำกลับมาใช้ใหม่ได้ดีเช่นเดียวกับสิ่งของทั่วไปไม่ค่อยมีข้อเสียเหล่านั้น ประเด็นคือการบำรุงรักษาเป็นค่าใช้จ่ายที่ใหญ่ที่สุดของซอฟต์แวร์ โดยทั่วไปการใช้ซ้ำเป็นความคิดที่ดี
Dan Gravell

2
หากต้องการ "เข้าถึงแพ็คเกจนี้โดยเฉพาะ" ให้วางrepo1.maven.org/maven2/commons-lang/commons-lang/2.5/…ลงใน classpath ของคุณ สิ่งประดิษฐ์ของ Maven นั้นคือcommons-lang: commons-lang: 2.5และพร้อมใช้งานจาก 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();
}

หมายเหตุ : คุณต้องเพิ่มการตรวจสอบข้อโต้แย้ง


1
คำตอบที่ดี แต่มันจะดีขึ้นเล็กน้อยถ้าชื่อเมธอดอธิบายความจริงที่ว่าสตริงถูกแบ่งหรือตรรกะนั้นถูก externalized และเมธอดการเรียกที่จัดตำแหน่งเป็นไพพ์เช่น "This_IS_AN_EXAMPLE_STRING" .removeUnderscores () toCamelCase () นำมาใช้ใหม่ได้มากขึ้น
Dan Gravell

1
ไม่จำเป็นต้องดีกว่า (แม้ว่าใช่มันสามารถใช้ซ้ำได้มากกว่า) เมื่อพูดถึงการจัดรูปแบบการตั้งชื่ออูฐสามารถ / ไม่บ่งบอกถึงการใช้เครื่องหมายขีดล่าง; ที่ด้านหลังของเหรียญมีการประชุมที่ระบุโดยใช้เครื่องหมายขีดล่าง ดังนั้นในใจของฉันนี่เป็นเพียงวิธีการแปลงจากรูปแบบหนึ่งเป็นรูปแบบอื่น
Matt Ball

58
ห้องสมุดฝรั่งของ Google มี enum ยูทิลิตี้ทั่วไปมากขึ้นสำหรับการแปลงระหว่างการประชุมทั่วไป String result = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "THIS_IS_AN_EXAMPLE_STRING");สำหรับกรณีนี้คุณจะทำอย่างไร ดูcom.google.common.base.CaseFormat Javadoc
George Hawkins

1
คำตอบนี้จะพบปัญหาเมื่อใช้ในภาษาเช่นภาษาตุรกี ... หากรหัสของคุณจะถูกใช้ในหลายภาษาให้ใช้ toUpperCase (Locale) และ toLowercase (Locale) .. ไม่ใช่คนที่ขึ้นอยู่กับสถานที่เริ่มต้น
vkraemer

2
@DanGravell: เมื่อคุณลบเครื่องหมายขีดล่างออกจะไม่สามารถแยกความแตกต่างของคำได้อีกต่อไป
njzk2

18

ด้วย Apache Commons Lang3 lib มันง่ายมาก

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

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

ตัวอย่าง:

getName("SOME_CONSTANT");

ให้:

"SomeConstant"

2
ในกรณีที่ชื่อตัวแปรนี้ไม่ถูกต้องเพราะชื่อจะต้องเริ่มต้นด้วยตัวพิมพ์เล็ก
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
การทดสอบความยาวไม่จำเป็น
njzk2

9

นี่คือข้อมูลโค้ดที่อาจช่วยได้:

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

วิธีนี้เหมาะสำหรับกรณี ALL_UPPER เป็น Camel แต่การเปลี่ยนแปลงเล็กน้อยในโปรแกรมยังสามารถจัดการ MixED_case หรือ lower_case (กรณีงู) ฉันได้แนะนำการแก้ไขหากได้รับอนุญาต
sud007

6

ตัวอย่าง Java 1.8 โดยใช้ 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ตอนนี้เป็นIsSomeText


ฉันชอบคำตอบนี้ แต่มีข้อบกพร่องถ้าสายอักขระที่มีอยู่แล้วในกรณีอูฐซึ่งในกรณีนี้มันเป็นตัวพิมพ์เล็กทั้งหมด เช่น abcDef จะกลายเป็น abcdef
mrswadge

การทดสอบโดยใช้text.matches( "([a-z]+[a-zA-Z0-9]+)+" )ก่อนปลอกอูฐน่าจะเป็นวิธีแก้ปัญหาที่เหมาะสมสำหรับปัญหาปลอกต่ำ
mrswadge

2

ไม่แน่ใจ แต่ฉันคิดว่าฉันสามารถใช้หน่วยความจำน้อยลงและรับประสิทธิภาพที่เชื่อถือได้ด้วยการทำแบบ char-by-char ฉันกำลังทำสิ่งที่คล้ายกัน แต่ในวนรอบในเธรดพื้นหลังดังนั้นฉันจึงลองตอนนี้ ฉันมีประสบการณ์บางอย่างกับ String.split ซึ่งมีราคาแพงกว่าที่คาดไว้ และฉันกำลังทำงานกับ Android และคาดว่า GC hiccups จะมีปัญหามากกว่านี้จากการใช้ซีพียู

  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 มีราคาแพงคืออินพุตของมันคือ regex (ไม่ใช่ตัวอักษรอย่าง String.indexOf) และจะส่งคืนอาร์เรย์ (แทนที่จะบอกว่าเป็นตัววนซ้ำเพราะวนรอบใช้เพียงหนึ่งสิ่งในแต่ละครั้ง) รวมทั้งกรณีเช่น "AB_AB_AB_AB_AB_AB ... " ทำลายประสิทธิภาพของการคัดลอกจำนวนมากใด ๆ และสำหรับสายยาวใช้คำสั่งขนาดหน่วยความจำมากขึ้นจากนั้นป้อนสตริง

ในขณะที่วนซ้ำผ่านตัวอักษรไม่มีกรณีที่ยอมรับ ดังนั้นสำหรับฉันค่าใช้จ่ายของ regex ที่ไม่จำเป็นและอาร์เรย์ดูเหมือนว่าโดยทั่วไปจะดีกว่าน้อยกว่า สนใจฟังความคิดเห็น / การแก้ไขขอบคุณ


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

เวลา: เป็นมิลลิวินาที

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

เยี่ยมเลยมันวนซ้ำกับอินพุต "This_IS_AN_EXAMPLE_STRING" หรือไม่
leorleor

@leorleor ซ้ำ = 1000000000 WithChars: เริ่มต้น = 1387547394726 ท้าย = 1387547889896 diff = 495170 WithRegex: start = 1387547889897 ท้าย = 1387548944739 diff = 1,054,842
ศรีสอ้าน

1

คุณสามารถใช้org.modeshape.common.text.Inflector

โดยเฉพาะ:

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

โดยค่าเริ่มต้นวิธีนี้จะแปลงสตริงเป็น UpperCamelCase

สิ่งประดิษฐ์ Maven คือ: org.modeshape: modeshape-common: 2.3.0.Final

บนที่เก็บ JBoss: https://repository.jboss.org/nexus/content/repositories/releases

นี่คือไฟล์ JAR: https://repository.jboss.org/nexus/content/repositories/releases/org/modeshape/modeshape-common/2.3.0.Final/modeshape-common-2.3.0.Final.jar


1

คุณสามารถลองสิ่งนี้ได้เช่นกัน:

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

นี่คือโปรแกรมที่ง่ายที่สุดในการแปลงเป็น CamelCase หวังว่ามันจะช่วยคุณ ..


0

มันจะแปลงEnum Constantเป็น Camel Case มันจะเป็นประโยชน์สำหรับทุกคนที่กำลังมองหา funtionality

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

อีกวิธีแก้ปัญหานี้อาจเป็นดังนี้

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

}

ภาวนาเป็น

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

เวลาดำเนินการ: 14 ms


0

ตัวอย่างง่ายๆ:

 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

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
คำตอบซ้ำ
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
CaseFormatไม่ใช่ API มาตรฐาน ทำซ้ำคำตอบถ้ามันเป็นฝรั่ง
Mark Jeronimus
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.