StringBuilder का अंतिम वर्ण निकालें?


422

जब आपको एक संग्रह के माध्यम से लूप करना पड़ता है और प्रत्येक डेटा को एक सीमांकक द्वारा अलग किया जाता है, तो आप हमेशा अंत में एक अतिरिक्त सीमांकक के साथ समाप्त होते हैं, जैसे।

for (String serverId : serverIds) {
  sb.append(serverId);
   sb.append(",");
}

कुछ इस तरह देता है: serverId_1, serverId_2, serverId_3,

मैं StringBuilder में अंतिम चरित्र को हटाना चाहूंगा (इसे परिवर्तित किए बिना क्योंकि मुझे इस लूप के बाद भी इसकी आवश्यकता है)।


11
अगर तार से जुड़ने का मतलब है कि आप "स्ट्रिंग कॉन्सेटेशन" हैं, तो यह स्ट्रिंग की संख्या और उनकी लंबाई पर निर्भर करता है। एक स्ट्रिंग बिल्डर का उपयोग करना अधिक कुशल है यदि आप स्ट्रिंग्स को बहुत अधिक स्ट्रिंग्स में रखने जा रहे हैं, क्योंकि स्ट्रिंग्स अपरिवर्तनीय हैं। हर बार जब आप एक साथ तार काटते हैं तो आप एक नया परिणामी स्ट्रिंग बनाते हैं (जो वास्तव में एक चार सरणी है)। स्ट्रिंग बिल्डरों अनिवार्य रूप से चार की एक सूची है जो तब तक अपरिवर्तनीय स्ट्रिंग नहीं बन जाती है जब तक आप स्ट्रींग () विधि को कॉल नहीं करते हैं।
डिस्लेक्सिकानबोको

4
यदि आप जावा 8 का उपयोग कर रहे हैं, तो बस उपयोग करें StringJoiner: stackoverflow.com/a/29169233/901641
ArtOfWarfare

जवाबों:


640

दूसरों ने deleteCharAtविधि बताई है , लेकिन यहाँ एक और वैकल्पिक तरीका है:

String prefix = "";
for (String serverId : serverIds) {
  sb.append(prefix);
  prefix = ",";
  sb.append(serverId);
}

वैकल्पिक रूप से, अमरूदJoiner से वर्ग का उपयोग करें :)

जावा 8 के रूप में, StringJoinerमानक JRE का हिस्सा है।


7
@ कोरोनटस: नहीं, क्योंकि "" किसी भी वर्ण की अनुपस्थिति है, एक वर्ण नहीं।
जॉन स्कीट

31
उपसर्ग निष्पादित नहीं करेगा = ","; हर लूप चक्र प्रदर्शन को प्रभावित करता है?
हरीश

21
@ हरीश: संभवतः, एक छोटा सा, थोड़ा सा - हालांकि बहुत महत्वपूर्ण होने की संभावना नहीं है।
जॉन स्कीट

4
@ हर्ष - और संभवतः बिल्कुल भी नहीं, अगर आशावादी पहले लूप पुनरावृत्ति को अनियंत्रित करता है।
स्टीफन सी

6
अपाचे कॉमन्स अमरूद है के लिए एक और विकल्प है Joinerउनके में भी StringUtilscommons.apache.org/proper/commons-lang/javadocs/api-2.6/org/… , java.lang.String)
GoRoS

419

एक और सरल उपाय है:

sb.setLength(sb.length() - 1);

एक अधिक जटिल समाधान:

उपरोक्त समाधान मानता है कि sb.length() > 0... हटाने के लिए एक "अंतिम चरित्र" है। यदि आप उस धारणा को नहीं बना सकते हैं, और / या आप उस अपवाद से नहीं निपट सकते हैं जो यह सुनिश्चित करेगा कि यदि धारणा गलत है, तो पहले StringBuilder की लंबाई जांचें; जैसे

// Readable version
if (sb.length() > 0) {
   sb.setLength(sb.length() - 1);
}

या

// Concise but harder-to-read version of the above.
sb.setLength(Math.max(sb.length() - 1, 0));

23
बहुत अच्छा समाधान है। प्रदर्शन पर सबसे कम प्रभाव और कम से कम कोड की आवश्यकता है :)
Alain O'Dea

186
if(sb.length() > 0){
    sb.deleteCharAt(sb.length() - 1);
}

33
यह बहुत अधिक हो जाता है, लेकिन यह कुशल नहीं है, यह एक system.arraycopy करता है। @Rohit रेड्डी कोरापोलु ने क्या कहा।
एलियनोस-

13
यह असुरक्षित के लिए है sb.length() == 0भी
मथायस

क्या यह सरोगेट जोड़ी के पात्रों के साथ सुरक्षित है?
रोज़गारपैक

यह मानते हुए कि अंतिम वर्ण अल्पविराम विभाजक है (उदाहरण के अनुसार), तब सरोगेट्स को कोई फर्क नहीं पड़ता है। यदि आपको सामान्य करने की आवश्यकता है तो separator.length()
स्टीफन सी

61

जावा 8 के अनुसार, स्ट्रिंग कक्षा में एक स्थिर विधि है join। पहला तर्क एक स्ट्रिंग है जिसे आप प्रत्येक जोड़ी के तार के बीच चाहते हैं, और दूसरा एक है Iterable<CharSequence>(जो दोनों इंटरफेस हैं, इसलिए कुछ List<String>काम करता है। तो आप बस ऐसा कर सकते हैं:

String.join(",", serverIds);

जावा 8 में भी, आप नए StringJoinerवर्ग का उपयोग कर सकते हैं , उन परिदृश्यों के लिए जहां आप स्ट्रिंग का निर्माण शुरू करना चाहते हैं इससे पहले कि आपके पास इसमें डालने के लिए तत्वों की पूरी सूची हो।


nvm ने आपके लिए संपादित किया अगर आपको कोई आपत्ति नहीं है, तो मेरी टिप्पणी को भी हटा दिया
Eugene

@ यूजीन - मैंने String.joinइसके बजाय पूरी तरह से ध्यान केंद्रित करने के लिए उत्तर को फिर से लिखा StringJoiner
आर्टऑफवर्फ

37

बस अंतिम चरित्र घटना की स्थिति प्राप्त करें।

for(String serverId : serverIds) {
 sb.append(serverId);
 sb.append(",");
}
sb.deleteCharAt(sb.lastIndexOf(","));

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

संपादित करें

जब से मुझे मेरे उत्तर पर धन्यवाद मिलता रहा है (धन्यवाद दोस्तों on), यह उसी के बारे में है:

पर जावा 8 आगे यह सिर्फ अधिक स्पष्ट और उपयोग करने के लिए स्पष्ट होगा StringJoiner । यह एक सरल विभाजक के लिए एक विधि है, और उपसर्ग और प्रत्यय के लिए एक अधिभार है।

यहाँ से लिए गए उदाहरण: उदाहरण

सरल विभाजक का उपयोग करके उदाहरण:

    StringJoiner mystring = new StringJoiner("-");    

    // Joining multiple strings by using add() method  
    mystring.add("Logan");  
    mystring.add("Magneto");  
    mystring.add("Rogue");  
    mystring.add("Storm");  

    System.out.println(mystring);

आउटपुट:

लोगान-चुंबक दुष्ट-तूफान

प्रत्यय और उपसर्ग के साथ उदाहरण:

    StringJoiner mystring = new StringJoiner(",", "(", ")");    

    // Joining multiple strings by using add() method  
    mystring.add("Negan");  
    mystring.add("Rick");  
    mystring.add("Maggie");  
    mystring.add("Daryl");  

    System.out.println(mystring);

उत्पादन

(Negan, रिक, मैगी, डेरिल)


आपको यकीन होगा कि अंतिम चरित्र एक है ,क्योंकि यह अंतिम विवरण था for looplastInfexOfपठनीयता के लिए अधिक है और यह एक नहीं brainer बनाने के लिए अगर आप याद करने के लिए अगर यह 0-सूचीबद्ध है या नहीं नहीं करना चाहती है। इसके अलावा, आपको स्ट्रिंगर की लंबाई के साथ मध्यस्थता करने की आवश्यकता नहीं है। यह सिर्फ सुविधा के लिए है।
रिबेल रिबेरो

34

इस मामले में,

sb.setLength(sb.length() - 1);

यह बेहतर है क्योंकि यह अंतिम मूल्य प्रदान करता है '\0'जबकि अंतिम चरित्र को हटाता हैSystem.arraycopy


1
setLengthकॉल अंतिम मान के लिए कुछ भी बताए नहीं है। जावा स्ट्रिंग बफ़र शून्य / शून्य नहीं हैं। वास्तव में, setLengthबस एक lengthक्षेत्र को अद्यतन कर रहा है ।
स्टीफन सी

@Rohit Reddy Korrapolu: लेकिन arraycopyप्रतियां 0 तत्व हैं, इसलिए मुझे लगता है कि यह दूर अनुकूलित हो सकता है।
मआर्टिनस

2
यदि नई लंबाई का तर्क वर्तमान लंबाई से अधिक या उसके बराबर है, तो पर्याप्त अशक्त वर्ण ('\ u0000') जोड़ दिए जाते हैं, ताकि लंबाई newLength तर्क बन जाए। जो मामला न हो।
fglez


11

एक और विकल्प

for(String serverId : serverIds) {
   sb.append(",");
   sb.append(serverId); 
}
sb.deleteCharAt(0);

2
अंतिम चार को हटाने से बेहतर होना चाहिए क्योंकि इसके लिए आकार की गणना की आवश्यकता होती है। जब तक पहले चार को हटाने के लिए डेटा चारों ओर ले जाया जाता है ...
slott

8

वैकल्पिक रूप से,

StringBuilder result = new StringBuilder();
for(String string : collection) {
    result.append(string);
    result.append(',');
}
return result.substring(0, result.length() - 1) ;

प्रयोग करने योग्य के रूप में आप एक "जोड़ सकते हैं।" अतं मै।
कलात्मक रूप से

6
StringBuilder sb = new StringBuilder();
sb.append("abcdef");
sb.deleteCharAt(sb.length() - 1);
assertEquals("abcde",sb.toString());
// true

5

फिर भी एक और विकल्प:

public String join(Collection<String> collection, String seperator) {
    if (collection.isEmpty()) return "";

    Iterator<String> iter = collection.iterator();
    StringBuilder sb = new StringBuilder(iter.next());
    while (iter.hasNext()) {
        sb.append(seperator);
        sb.append(iter.next());
    }

    return sb.toString();
}

3

TextUtils.isEmpty का prefixउपयोग करने के प्रदर्शन (प्रदर्शन को प्रभावित) से बचने के लिए:

            String prefix = "";
            for (String item : list) {
                sb.append(prefix);
                if (TextUtils.isEmpty(prefix))
                    prefix = ",";
                sb.append(item);
            }

TestUtils किस तरह के पैकेज से संबंधित है?
मार्कस

@ मर्कस android.text.TextUtils
NickUnuchek

1

आप अपने उत्पन्न पाठ से अंतिम चरित्र को हटाने के बजाय 'जॉइनर' वर्ग का उपयोग करने का प्रयास कर सकते हैं;

                List<String> textList = new ArrayList<>();
                textList.add("text1");
                textList.add("text2");
                textList.add("text3");

                Joiner joiner = Joiner.on(",").useForNull("null");
                String output = joiner.join(textList);

               //output : "text1,text2,text3"

1

मैं नीचे जैसा कुछ कर रहा हूं:

    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < value.length; i++) {
        stringBuilder.append(values[i]);
        if (value.length-1) {
            stringBuilder.append(", ");
        }
    }

0

यहाँ एक और उपाय है:

for(String serverId : serverIds) {
   sb.append(",");
   sb.append(serverId); 
}

String resultingString = "";
if ( sb.length() > 1 ) {
    resultingString = sb.substring(1);
}

1
ओह मैं समझा। आप स्ट्रिंग स्ट्रिंग नहीं बल्कि स्ट्रिंग पर कॉल कर रहे हैं।
स्टीफन सी

लेकिन वैसे भी, यह 2010 से जकी के समाधान पर एक छोटा संस्करण है।
स्टीफन सी

0

मैं व्यक्तिगत रूप से अंत में एक बैकस्पेस चरित्र (या अधिक समय के लिए "सीमांकक") जोड़ना पसंद करता हूं:

for(String serverId : serverIds) {
    sb.append(serverId);
    sb.append(",");
}

sb.append('\b');

ध्यान दें कि इसमें समस्याएं हैं:

  • कैसे \bप्रदर्शित किया जाता है यह पर्यावरण पर निर्भर करता है,
  • length()की Stringसामग्री "दृश्यमान" वर्णों की लंबाई से अलग हो सकता

जब \bओके दिखता है और लंबाई कोई बात नहीं है जैसे कि कंसोल पर लॉग इन करना, यह मुझे काफी अच्छा लगता है।


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