स्ट्रिंग के निचले मामले का पहला चरित्र बनाने का सबसे कुशल तरीका?


101

Stringनिचले मामले का पहला चरित्र बनाने के लिए सबसे कुशल तरीका क्या है ?

मैं इसे करने के कई तरीकों के बारे में सोच सकता हूं:

के charAt()साथ उपयोग कर रहा हैsubstring()

String input   = "SomeInputString";
String output  = Character.toLowerCase(input.charAt(0)) +
                   (input.length() > 1 ? input.substring(1) : "");

या एक charसरणी का उपयोग कर

 String input  = "SomeInputString";
 char c[]      = input.toCharArray();
 c[0]          = Character.toLowerCase(c[0]);
 String output = new String(c);

मुझे यकीन है कि इसे प्राप्त करने के कई अन्य शानदार तरीके हैं। आप क्या सलाह देते हैं?


सबसे अच्छा तरीका यदि संभव हो तो अपनी आवश्यकताओं को बदलना होगा। एक स्ट्रिंग के बजाय एक स्ट्रिंगब्यूरी स्वीकार करें और आप इसे सीधे संशोधित कर सकते हैं।
मार्क पीटर्स

खैर यह एक उत्तर नहीं है क्योंकि यह जावा के बाहर है, और एएससीआईआई एन्कोडिंग पर निर्भर करता है और यह जानने पर कि चरित्र पहले से ही वर्णनात्मक है। यह एक पुराने समय की हैक है:c[0] |= ' ';
माइक डनलवे


यह एक अलग सवाल है
एंडी

जवाबों:


126

मैंने जेएमएच का उपयोग कर आशाजनक दृष्टिकोणों का परीक्षण किया । पूर्ण बेंचमार्क कोड

परीक्षणों के दौरान मान लेना (हर बार कोने के मामलों की जाँच से बचने के लिए): इनपुट स्ट्रिंग की लंबाई हमेशा 1 से अधिक होती है।

परिणाम

Benchmark           Mode  Cnt         Score        Error  Units
MyBenchmark.test1  thrpt   20  10463220.493 ± 288805.068  ops/s
MyBenchmark.test2  thrpt   20  14730158.709 ± 530444.444  ops/s
MyBenchmark.test3  thrpt   20  16079551.751 ±  56884.357  ops/s
MyBenchmark.test4  thrpt   20   9762578.446 ± 584316.582  ops/s
MyBenchmark.test5  thrpt   20   6093216.066 ± 180062.872  ops/s
MyBenchmark.test6  thrpt   20   2104102.578 ±  18705.805  ops/s

स्कोर प्रति सेकंड ऑपरेशन हैं, जितना बेहतर होगा।

टेस्ट

  1. test1 पहले एंडी और हेलिंक का दृष्टिकोण था:

    string = Character.toLowerCase(string.charAt(0)) + string.substring(1);
  2. test2दूसरा एंडी का दृष्टिकोण था। यह Introspector.decapitalize()डैनियल द्वारा भी सुझाया गया है, लेकिन दो ifबयानों के बिना । पहले ifपरीक्षण धारणा के कारण हटा दिया गया था। दूसरे को हटा दिया गया था, क्योंकि यह शुद्धता का उल्लंघन कर रहा था (यानी इनपुट "HI"वापस आ जाएगा "HI")। यह लगभग सबसे तेज था।

    char c[] = string.toCharArray();
    c[0] = Character.toLowerCase(c[0]);
    string = new String(c);
  3. test3का एक संशोधन था test2, लेकिन इसके बजाय Character.toLowerCase(), मैं 32 जोड़ रहा था, जो सही ढंग से काम करता है अगर और केवल अगर स्ट्रिंग ASCII में है। यह सबसे तेज था। c[0] |= ' 'माइक की टिप्पणी से भी यही प्रदर्शन हुआ।

    char c[] = string.toCharArray();
    c[0] += 32;
    string = new String(c);
  4. test4इस्तेमाल किया StringBuilder

    StringBuilder sb = new StringBuilder(string);
    sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
    string = sb.toString();
  5. test5दो substring()कॉल का उपयोग किया ।

    string = string.substring(0, 1).toLowerCase() + string.substring(1);
  6. test6char value[]सीधे स्ट्रिंग में बदलने के लिए प्रतिबिंब का उपयोग करता है । यह सबसे धीमा था।

    try {
        Field field = String.class.getDeclaredField("value");
        field.setAccessible(true);
        char[] value = (char[]) field.get(string);
        value[0] = Character.toLowerCase(value[0]);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }

निष्कर्ष

यदि स्ट्रिंग की लंबाई हमेशा 0 से अधिक है, तो उपयोग करें test2

यदि नहीं, तो हमें कोने के मामलों की जाँच करनी होगी:

public static String decapitalize(String string) {
    if (string == null || string.length() == 0) {
        return string;
    }

    char c[] = string.toCharArray();
    c[0] = Character.toLowerCase(c[0]);

    return new String(c);
}

यदि आप सुनिश्चित हैं कि आपका पाठ हमेशा ASCII में होगा और आप चरम प्रदर्शन की तलाश कर रहे हैं, क्योंकि आपको यह कोड अड़चन में मिला, उपयोग करें test3


95

यदि आप तीसरे पक्ष के पुस्तकालय का उपयोग नहीं करना चाहते हैं तो मुझे एक अच्छा विकल्प मिला है:

import java.beans.Introspector;

Assert.assertEquals("someInputString", Introspector.decapitalize("SomeInputString"));

14
इस विधि के लिए डॉक्टर से: "इसका सामान्य अर्थ है कि ऊपरी चरित्र से निचले मामले में पहले वर्ण को परिवर्तित करना, लेकिन (असामान्य) विशेष मामले में जब एक से अधिक वर्ण होते हैं और पहले और दूसरे वर्ण दोनों ऊपरी मामले होते हैं, तो हम छोड़ देते हैं यह अकेला है। "
एंडी

1
स्रोत को देखते हुए, एक बार यह विधि पिछली टिप्पणी में वर्णित विशेष मामले को संभालती है, यह केवल चार सरणी का उपयोग करती है जैसा कि मैंने अपने प्रश्न में उल्लेख किया था।
एंडी

2
बिल्कुल वही जो मुझे चाहिए था। Introspector.decapitalize ("एबीसी") अभी भी एबीसी होगा। WordUtils.uncapitalize ("एबीसी") "एबीसी" का उत्पादन करता है। बस यह साझा करते हुए कि पूर्व कैसा होता है, वसंत अपने सेम का ऑटोनोमिंग कैसे करता है, इसलिए यदि आपको एबीसीएस सेवा नाम के सेम नाम से पुनः प्राप्त करने की आवश्यकता है, तो यह एबीसीएस सेवा नहीं है, लेकिन एबीसीएस सर्विस।
ग्रामीण

21

यह स्ट्रिंग परिवर्तन की बात आती है जकार्ता कॉमन्स लैंग को एक बार देख ले StringUtils


8
विशेष रूप से, स्ट्रीप यूटिल्स का उपयोग करने की विधि अनपिटल (java.lang.String) आपके कोड में NullPointerException के बारे में चिंता न करने का अतिरिक्त लाभ है।
हेक्सियम

3
जरूरी नहीं कि सबसे कुशल हो, लेकिन शायद सबसे स्पष्ट, जो बहुत मायने रखता है।
डेविड गेलर

2
निर्भर करता है कि आप किस संसाधन को अधिक कुशल बना रहे हैं - CPU या प्रोग्रामर समय :)
Dan Gravell

15

यदि आप अपाचे कॉमन्स का उपयोग करना चाहते हैं तो आप निम्न कार्य कर सकते हैं:

import org.apache.commons.lang3.text.WordUtils;
[...] 
String s = "SomeString"; 
String firstLower = WordUtils.uncapitalize(s);

परिणाम: someString


3
यह अच्छा और साफ समाधान है, लेकिन यह अब पदावनत है, हमें कॉमन्स-टेक्स्ट का उपयोग करना चाहिए:compile group: 'org.apache.commons', name: 'commons-text', version: '1.2'
dk7

10

चार उन्मुख दृष्टिकोण के बावजूद मैं एक स्ट्रिंग उन्मुख समाधान का सुझाव दूंगा। String.toLowerCase लोकेल विशिष्ट है, इसलिए मैं इस मुद्दे को ध्यान में रखूंगाString.toLowerCaseके अनुसार कम caseing के लिए पसंद करते हैं करने के लिए है Character.toLowerCase । इसके अलावा एक चार उन्मुख समाधान पूर्ण यूनिकोड संगत नहीं है, क्योंकि Character.toLowerCase पूरक वर्णों को संभाल नहीं सकता है।

public static final String uncapitalize(final String originalStr,
            final Locale locale) {
        final int splitIndex = 1;
        final String result;
        if (originalStr.isEmpty()) {
        result = originalStr;
        } else {
        final String first = originalStr.substring(0, splitIndex).toLowerCase(
                locale);
        final String rest = originalStr.substring(splitIndex);
        final StringBuilder uncapStr = new StringBuilder(first).append(rest);
        result = uncapStr.toString();
        }
        return result;
    }

अद्यतन: एक उदाहरण के रूप में हम लोकल सेटिंग को Iतुर्की और जर्मन में कितना महत्वपूर्ण बनाते हैं :

System.out.println(uncapitalize("I", new Locale("TR","tr")));
System.out.println(uncapitalize("I", new Locale("DE","de")));

दो अलग-अलग परिणामों का उत्पादन करेगा:

मैं

मैं


7

जावा में स्ट्रिंग्स अपरिवर्तनीय हैं, इसलिए किसी भी तरह एक नया स्ट्रिंग बनाया जाएगा।

आपका पहला उदाहरण शायद थोड़ा अधिक कुशल होगा क्योंकि इसे केवल एक नया स्ट्रिंग बनाने की आवश्यकता है न कि एक अस्थायी चरित्र सरणी।


1
दरअसल, पहला तरीका एक अस्थायी स्ट्रिंग (प्रतिस्थापन के लिए) बनाता है, जो चरित्र सरणी से अधिक महंगा है।
हॉट लिक्स

1
डेटा का समर्थन किए बिना
अनसुना

3

एक बहुत ही छोटी और सरल स्थैतिक विधि जिसे आप चाहते हैं उसे संग्रहित करें:

public static String decapitalizeString(String string) {
    return string == null || string.isEmpty() ? "" : Character.toLowerCase(string.charAt(0)) + string.substring(1);
}

2

यदि आपको जो चाहिए वह बहुत ही सरल है (जैसे जावा वर्ग के नाम, कोई स्थान नहीं), तो आप Google अमरूद पुस्तकालय में CaseFormat वर्ग का भी उपयोग कर सकते हैं ।

String converted = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, "FooBar");
assertEquals("fooBar", converted);

या आप एक कनवर्टर ऑब्जेक्ट को तैयार और पुन: उपयोग कर सकते हैं, जो अधिक कुशल हो सकता है।

Converter<String, String> converter=
    CaseFormat.UPPER_CAMEL.converterTo(CaseFormat.LOWER_CAMEL);

assertEquals("fooBar", converter.convert("FooBar"));

Google अमरूद स्ट्रिंग हेरफेर के दर्शन को बेहतर ढंग से समझने के लिए, इस विकी पृष्ठ को देखें


1
String testString = "SomeInputString";
String firstLetter = testString.substring(0,1).toLowerCase();
String restLetters = testString.substring(1);
String resultString = firstLetter + restLetters;

1

मैं आज ही इस पर विचार कर रहा हूं। सबसे पैदल रास्ते में खुद ऐसा करने की कोशिश की। कि एक लाइन ले ली, थोंग लोंगिश। यहाँ जाता हैं

String str = "TaxoRank"; 

System.out.println(" Before str = " + str); 

str = str.replaceFirst(str.substring(0,1), str.substring(0,1).toLowerCase());

System.out.println(" After str = " + str);

देता है:

Str से पहले = TaxoRanks

Str = taxoRanks के बाद


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.