जावा: सूची <स्ट्रिंग> को स्ट्रिंग में परिवर्तित करें


594

जावास्क्रिप्ट है Array.join()

js>["Bill","Bob","Steve"].join(" and ")
Bill and Bob and Steve

क्या जावा में ऐसा कुछ है? मुझे पता है कि मैं खुद को स्ट्रिंगबुलस्टाइल के साथ कुछ कर सकता हूं:

static public String join(List<String> list, String conjunction)
{
   StringBuilder sb = new StringBuilder();
   boolean first = true;
   for (String item : list)
   {
      if (first)
         first = false;
      else
         sb.append(conjunction);
      sb.append(item);
   }
   return sb.toString();
}

... लेकिन ऐसा करने का कोई मतलब नहीं है अगर कुछ ऐसा है जो पहले से ही जेडीके का हिस्सा है।



18
सख्ती से संबंधित नहीं है, लेकिन एंड्रॉइड में उनके TextUtils वर्ग के हिस्से के रूप में एक शामिल समारोह में बनाया गया है: developer.android.com/reference/android/text/… , java.lang.Iterable)
Xavi

16
जावा 8 की एक String.join()विधि है। इस उत्तर पर एक नज़र डालें यदि आप Java 8 (या नए) stackoverflow.com/a/22577565/1115554
micha

जवाबों:


762

Java 8 के साथ आप बिना किसी थर्ड पार्टी लाइब्रेरी के ऐसा कर सकते हैं।

यदि आप स्ट्रिंग्स के संग्रह में शामिल होना चाहते हैं, तो आप नई String.join () विधि का उपयोग कर सकते हैं :

List<String> list = Arrays.asList("foo", "bar", "baz");
String joined = String.join(" and ", list); // "foo and bar and baz"

यदि आपके पास स्ट्रिंग की तुलना में किसी अन्य प्रकार का संग्रह है, तो आप शामिल होने वाले कलेक्टर के साथ स्ट्रीम एपीआई का उपयोग कर सकते हैं :

List<Person> list = Arrays.asList(
  new Person("John", "Smith"),
  new Person("Anna", "Martinez"),
  new Person("Paul", "Watson ")
);

String joinedFirstNames = list.stream()
  .map(Person::getFirstName)
  .collect(Collectors.joining(", ")); // "John, Anna, Paul"

StringJoinerवर्ग भी उपयोगी हो सकता है।


7
दुर्भाग्य से, String.join केवल CharSequences स्वीकार करता है और न कि वस्तुओं की आशा करता है। यह भी निश्चित नहीं है कि यह अशक्त है
मार्क

@ मर्कassertThat(String.join(", ", Lists.newArrayList("1", null)), is("1, null"));
ली

स्ट्रिंगरजॉइनर विशेष रूप से उपयोगी है अगर कोई [a, b, c]ब्रेसिज़ सहित किसी चीज़ से जुड़ना चाहता है ।
अगस्त को कोपोर

@Marc String.join भी स्वीकार करता है Iterable<CharSequence>; इंटरफ़ेस संबंध:Iterable -> Collection -> List
एएफएफ

306

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

आप साधारण ज्वाइन केस के साथ कर सकते हैं

Joiner.on(" and ").join(names)

लेकिन यह भी आसानी से नल के साथ सौदा:

Joiner.on(" and ").skipNulls().join(names);

या

Joiner.on(" and ").useForNull("[unknown]").join(names);

और (जहाँ तक मैं कॉमन्स-लैंग को वरीयता देने में उपयोग करने के लिए चिंतित हूँ, उपयोगी है), मैप्स से निपटने की क्षमता:

Map<String, Integer> ages = .....;
String foo = Joiner.on(", ").withKeyValueSeparator(" is ").join(ages);
// Outputs:
// Bill is 25, Joe is 30, Betty is 35

जो डिबगिंग आदि के लिए बेहद उपयोगी है।


10
प्लग के लिए धन्यवाद! हमारे योजक भी आपको इंटरएक्टिव स्ट्रिंग्स बनाने के बिना सीधे एक एपेंडेबल (जैसे एक स्ट्रिंगबर्ल, या किसी भी लेखक) के लिए अपील करने का विकल्प देता है, जिसमें अपाचे पुस्तकालय की कमी लगती है।
केविन बोर्रिलियन

2
यह बहुत अच्छा है, लेकिन क्या आप कृपया एक .useForLastSeparator()या कुछ इसी तरह की विधि जोड़ सकते हैं ? इस तरह, आप कुछ प्राप्त कर सकते हैं ", और" केवल अंतिम दो वस्तुओं के बीच ("," बाकी के लिए)।
जेफ इवांस

2
हाँ, यह धागा सुरक्षित है। एक योजक में बचा एकमात्र राज्य है separator(जो है final)। अमरुद में जो कुछ भी मैंने देखा है, जहां मैं एक अपाचे कॉमन्स के बराबर का उपयोग करता था वह बहुत बेहतर है (कम पढ़ें: क्लीनर, तेज, सुरक्षित और सामान्य रूप से अधिक मजबूत) अमरूद में कम किनारे वाले मामले में विफलताओं और थ्रेड सुरक्षा के मुद्दे और छोटी स्मृति पदचिह्न। उनका "सबसे अच्छा तरीका संभव" मार्गदर्शक प्रिंसिपल अब तक सही है।
शैडो मैन

यदि आपको विपरीत दिशा में जाने की आवश्यकता है (यानी, टुकड़ों में एक स्ट्रिंग को विभाजित करना), तो अमरूद वर्ग स्प्लिटर की जांच करें - बहुत अच्छी तरह से डिज़ाइन / कार्यान्वित।
मैट पासेल

जावा 8 में, एक String.join()विधि और एक StringJoinerवर्ग है।
theTechnoKid

138

बॉक्स से बाहर नहीं है, लेकिन कई पुस्तकालयों के समान है:

कॉमन्स लैंग:

org.apache.commons.lang.StringUtils.join(list, conjunction);

वसंत:

org.springframework.util.StringUtils.collectionToDelimitedString(list, conjunction);

125

पर एंड्रॉयड आप इस्तेमाल कर सकते हैं TextUtils वर्ग।

TextUtils.join(" and ", names);

11
मुझे इसकी तलाश थी। एंड्रॉयड पर न्यूनतम एपीआई स्तर 26 कीString.join आवश्यकता है ।
okarakose

49

नहीं, मानक जावा एपीआई में ऐसी कोई सुविधा विधि नहीं है।

आश्चर्य की बात नहीं है, अपाचे कॉमन्स अपने StringUtils वर्ग में ऐसी चीज प्रदान करते हैं, जब आप इसे स्वयं नहीं लिखना चाहते हैं।


11
यह मुझे हमेशा गुदगुदाता है कि स्ट्रिंग में विभाजन है लेकिन जुड़ाव नहीं है। एक तरह से यह समझ में आता है कि यह करता है, लेकिन यह सिर्फ कष्टप्रद है कि स्ट्रिंग में इसके लिए कम से कम एक स्थिर तरीका नहीं है।
21

3
मैं तुम्हारे साथ हूँ Bemrose। कम से कम वे हमें एक दिया isEmpty()बजाय विधि एक (स्थिर) join()में विधि String:): rollseyes: ...
बार्ट Kiers

41

जावा 8 में तीन संभावनाएँ:

List<String> list = Arrays.asList("Alice", "Bob", "Charlie")

String result = String.join(" and ", list);

result = list.stream().collect(Collectors.joining(" and "));

result = list.stream().reduce((t, u) -> t + " and " + u).orElse("");

27

एक जावा 8 कलेक्टर के साथ, यह निम्नलिखित कोड के साथ किया जा सकता है:

Arrays.asList("Bill", "Bob", "Steve").stream()
.collect(Collectors.joining(" and "));

इसके अलावा, जावा 8 में सबसे सरल उपाय:

String.join(" and ", "Bill", "Bob", "Steve");

या

String.join(" and ", Arrays.asList("Bill", "Bob", "Steve"));

21

मैंने इसे लिखा है (मैं इसका उपयोग सेम और शोषण के लिए करता हूं toString, इसलिए इसे न लिखें Collection<String>):

public static String join(Collection<?> col, String delim) {
    StringBuilder sb = new StringBuilder();
    Iterator<?> iter = col.iterator();
    if (iter.hasNext())
        sb.append(iter.next().toString());
    while (iter.hasNext()) {
        sb.append(delim);
        sb.append(iter.next().toString());
    }
    return sb.toString();
}

लेकिन CollectionJSP द्वारा समर्थित नहीं है, इसलिए TLD के लिए मैंने लिखा है:

public static String join(List<?> list, String delim) {
    int len = list.size();
    if (len == 0)
        return "";
    StringBuilder sb = new StringBuilder(list.get(0).toString());
    for (int i = 1; i < len; i++) {
        sb.append(delim);
        sb.append(list.get(i).toString());
    }
    return sb.toString();
}

और .tldफ़ाइल में डाल दिया :

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
    <function>
        <name>join</name>
        <function-class>com.core.util.ReportUtil</function-class>
        <function-signature>java.lang.String join(java.util.List, java.lang.String)</function-signature>
    </function>
</taglib>

और JSP फ़ाइलों में इसका उपयोग करें:

<%@taglib prefix="funnyFmt" uri="tag:com.core.util,2013:funnyFmt"%>
${funnyFmt:join(books, ", ")}

1
बदलने के Collection<>लिए सुझाव Iterable<>?
जेसन एस

@ जैसन +1। अच्छी बात है, लेकिन पढ़ें stackoverflow.com/questions/1159797/…
gavenkoa

19

यदि आपके पास JDK का उपयोग बिना किसी बाहरी लाइब्रेरी के करना चाहते हैं तो कोड आपके पास करने का सही तरीका है। कोई सरल "वन-लाइनर" नहीं है जिसे आप जेडीके में उपयोग कर सकते हैं।

यदि आप बाहरी देयता का उपयोग कर सकते हैं, तो मेरा सुझाव है कि आप org.apache.commons.lang.StringUtils में देखें Apache Commons लाइब्रेरी क्लास देखें।

उपयोग का एक उदाहरण:

List<String> list = Arrays.asList("Bill", "Bob", "Steve");
String joinedResult = StringUtils.join(list, " and ");

17

इसे प्राप्त करने का एक रूढ़िवादी तरीका है, एक नए कार्य को परिभाषित करके:

public static String join(String joinStr, String... strings) {
    if (strings == null || strings.length == 0) {
        return "";
    } else if (strings.length == 1) {
        return strings[0];
    } else {
        StringBuilder sb = new StringBuilder(strings.length * 1 + strings[0].length());
        sb.append(strings[0]);
        for (int i = 1; i < strings.length; i++) {
            sb.append(joinStr).append(strings[i]);
        }
        return sb.toString();
    }
}

नमूना:

String[] array = new String[] { "7, 7, 7", "Bill", "Bob", "Steve",
        "[Bill]", "1,2,3", "Apple ][","~,~" };

String joined;
joined = join(" and ","7, 7, 7", "Bill", "Bob", "Steve", "[Bill]", "1,2,3", "Apple ][","~,~");
joined = join(" and ", array); // same result

System.out.println(joined);

आउटपुट:

7, 7, 7 और बिल और बॉब और स्टीव और [बिल] और 1,2,3 और एप्पल] [और ~, ~


5
एक विधि पैरामीटर को उसी नाम के रूप में देना, जिस विधि के रूप में संभवतः सबसे अच्छा विचार नहीं है। separatorबहुत अधिक विचारोत्तेजक होगा।
ccpizza

10

जावा 8 समाधान के साथ java.util.StringJoiner

जावा 8 को एक StringJoinerवर्ग मिला है । लेकिन आपको अभी भी बॉयलरप्लेट का एक सा लिखना होगा, क्योंकि यह जावा है।

StringJoiner sj = new StringJoiner(" and ", "" , "");
String[] names = {"Bill", "Bob", "Steve"};
for (String name : names) {
   sj.add(name);
}
System.out.println(sj);

यदि आप अधिक सुविधाजनक विधि String.join () का उपयोग करते हैं, तो आपको थोड़ा बॉयलरप्लेट लिखने की आवश्यकता नहीं है ।
एंडी थॉमस

9

आप अपाचे कॉमन्स लाइब्रेरी का उपयोग कर सकते हैं, जिसमें एक स्ट्रिंग स्ट्रिंग क्लास और एक जॉइन विधि है।

इस लिंक की जाँच करें: https://commons.apache.org/proper/commons-lang/javadocs/api.2.0/org/apache/commons/lang/StringUtils.html

ध्यान दें कि ऊपर दिया गया लिंक समय के साथ अप्रचलित हो सकता है, जिस स्थिति में आप बस "अपाचे कॉमन्स स्ट्रिंगिंगटिल्स" के लिए वेब खोज सकते हैं, जिससे आपको नवीनतम संदर्भ खोजने की अनुमति मिल सकती है।

(इस सूत्र से संदर्भित) C # String.Format () और String.Join () के जावा समकक्ष


7

तुम यह केर सकते हो:

String aToString = java.util.Arrays.toString(anArray);
// Do not need to do this if you are OK with '[' and ']'
aToString = aToString.substring(1, aToString.length() - 1);

या एक लाइनर (केवल जब आप '[' और ']') नहीं चाहते

String aToString = java.util.Arrays.toString(anArray).substring(1).replaceAll("\\]$", "");

उम्मीद है की यह मदद करेगा।


1
यह पसंद के संयोजन को जोड़ नहीं देगा।
21

ओह !! मुझे खेद है, मैंने वह जगह नहीं ली।
नवामन

6

शुद्ध JDK के साथ एक ड्यूटी लाइन में इसे करने का एक मजेदार तरीका:

String[] array = new String[] { "Bill", "Bob", "Steve","[Bill]","1,2,3","Apple ][" };
String join = " and ";

String joined = Arrays.toString(array).replaceAll(", ", join)
        .replaceAll("(^\\[)|(\\]$)", "");

System.out.println(joined);

आउटपुट:

बिल और बॉब और स्टीव और [बिल] और 1,2,3 और Apple] [


एक बहुत सही नहीं है और बहुत मजेदार तरीका नहीं है!

String[] array = new String[] { "7, 7, 7","Bill", "Bob", "Steve", "[Bill]",
        "1,2,3", "Apple ][" };
String join = " and ";

for (int i = 0; i < array.length; i++) array[i] = array[i].replaceAll(", ", "~,~");
String joined = Arrays.toString(array).replaceAll(", ", join)
        .replaceAll("(^\\[)|(\\]$)", "").replaceAll("~,~", ", ");

System.out.println(joined);

आउटपुट:

7, 7, 7 और बिल और बॉब और स्टीव और [बिल] और 1,2,3 और Apple] [


इसे "[बिल]", "1,2,3" और "ऐप्पल] [" के साथ आज़माएं। रचनात्मक, लेकिन इसमें ऐसे मामले हैं जो गलत हैं।
जेसन एस

1
अब इसे "~, ~" के साथ आज़माएँ। आप इस तरह की वास्तुकला के साथ पूरी तरह से बुलेटप्रूफ एक कार्यक्रम नहीं बना सकते हैं।
जेसन एस

हाँ, मुझे पता है ... मैं नीचे हटा दिया है। लेकिन आपको यहां उत्तर पोस्ट करने के बारे में थोड़ा और ध्यान से सोचना चाहिए, खासकर इस तरह के सवालों के लिए जो कई साल पुराने हैं। न केवल मूल पोस्टर पर तुरंत उत्तर उपयोगी होते हैं, बल्कि वे Google खोजों पर भी दिखाई देते हैं। (वास्तव में, ऐसे प्रश्न जो कई साल पुराने हैं, नए उत्तरों का मूल पोस्टर के लिए कोई मूल्य नहीं हो सकता है ।) समाधान जिसमें कमियां या त्रुटियां हैं, वे उन लोगों के लिए हानिकारक हो सकते हैं जो इसे बाद में संदर्भ से बाहर पाते हैं।
जेसन एस

1
मैं यहां दूसरों से बहुत कुछ सीखता हूं, जैसे कि मेरा कोई सही समाधान नहीं, बल्कि वास्तव में ज्ञान, और पक्ष की सोच से समृद्ध है। दूसरों के लिए आराम करें, प्रत्येक को यह समझना चाहिए कि उनके कोड की प्रत्येक पंक्ति क्या करती है। याद रखें कि प्रोग्रामिंग एक कला की तरह है, और यहां तक ​​कि कोड की प्रत्येक पंक्ति का मतलब प्रोग्रामर व्यक्तित्व के बारे में कुछ है। और हाँ, मैं उत्पादन में इस कोड का उपयोग नहीं करूंगा!
डैनियल डे लियोन


4

यदि आप ग्रहण संग्रह (पूर्व में जीएस संग्रह ) का उपयोग कर रहे हैं , तो आप makeString()विधि का उपयोग कर सकते हैं ।

List<String> list = Arrays.asList("Bill", "Bob", "Steve");

String string = ListAdapter.adapt(list).makeString(" and ");

Assert.assertEquals("Bill and Bob and Steve", string);

यदि आप अपने Listको ग्रहण संग्रह में बदल सकते हैं , तो आप एडॉप्टर से छुटकारा पा सकते हैं।

MutableList<String> list = Lists.mutable.with("Bill", "Bob", "Steve");
String string = list.makeString(" and ");

यदि आप बस एक अल्पविराम से अलग स्ट्रिंग चाहते हैं, तो आप उस संस्करण का उपयोग कर सकते हैं जिसमें makeString()कोई पैरामीटर नहीं है।

Assert.assertEquals(
    "Bill, Bob, Steve", 
    Lists.mutable.with("Bill", "Bob", "Steve").makeString());

नोट: मैं एक्लिप्स कलेक्शंस के लिए कमिट हूं।


3

जावा के साथ 1.8 स्ट्रीम का उपयोग किया जा सकता है,

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
List<String> list = Arrays.asList("Bill","Bob","Steve").
String str = list.stream().collect(Collectors.joining(" and "));

3

संपादित करें

मैं भी नोटिस करता हूं toString() अंतर्निहित कार्यान्वयन के मुद्दे हूं, और विभाजक वाले तत्व के बारे में लेकिन मुझे लगा कि मुझे पागल किया जा रहा है।

चूंकि मुझे उस संबंध में दो टिप्पणियां मिली हैं, इसलिए मैं अपना जवाब बदल रहा हूं:

static String join( List<String> list , String replacement  ) {
    StringBuilder b = new StringBuilder();
    for( String item: list ) { 
        b.append( replacement ).append( item );
    }
    return b.toString().substring( replacement.length() );
}

जो मूल प्रश्न के समान सुंदर लगता है।

इसलिए यदि आप ऐसा महसूस नहीं करते हैं कि आप अपनी परियोजना में पूरे जार को जोड़ सकते हैं तो आप इसका उपयोग कर सकते हैं।

मुझे लगता है कि आपके मूल कोड में कुछ भी गलत नहीं है। वास्तव में, सभी का सुझाव देने वाला विकल्प लगभग एक जैसा दिखता है (हालांकि यह कई अतिरिक्त सत्यापन करता है)

यहां यह अपाचे 2.0 लाइसेंस के साथ है।

public static String join(Iterator iterator, String separator) {
    // handle null, zero and one elements before building a buffer
    if (iterator == null) {
        return null;
    }
    if (!iterator.hasNext()) {
        return EMPTY;
    }
    Object first = iterator.next();
    if (!iterator.hasNext()) {
        return ObjectUtils.toString(first);
    }

    // two or more elements
    StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
    if (first != null) {
        buf.append(first);
    }

    while (iterator.hasNext()) {
        if (separator != null) {
            buf.append(separator);
        }
        Object obj = iterator.next();
        if (obj != null) {
            buf.append(obj);
        }
    }
    return buf.toString();
}

अब हम जानते हैं, शुक्रिया खुला स्रोत


यह अब काम करेगा, लेकिन आप यह सुनिश्चित नहीं कर सकते कि भविष्य में List.toString () कैसे व्यवहार करेगा। मैं प्रश्न में वस्तु के बारे में कुछ सूचनात्मक स्ट्रिंग को मुद्रित करने के अलावा एक toString () संचालन पर भरोसा नहीं करूंगा। आपके बचाव में, आप एकमात्र ऐसा व्यक्ति नहीं हैं जो इस समाधान का प्रस्ताव करता है।
हंस डोगेने

क्या होगा अगर सूची में एक तत्व की सामग्री में विकल्प शामिल हैं ", "?
बार्ट कीर्स

@ हंस और @ कार्ट: आप सही कह रहे हैं। मुझे लगा कि कोई और नोटिस नहीं करेगा: पी मैं अपना जवाब बदल रहा हूं।
ऑस्करराइज

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

2

Google के Guava API में भी .join () है, हालाँकि (जैसा कि अन्य उत्तरों के साथ स्पष्ट होना चाहिए), Apache Commons यहाँ मानक से बहुत अधिक है।


1

जावा 8 लाता है

Collectors.joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)

विधि, जो prefix + suffixशून्य मानों के लिए उपयोग करके अशक्त है।

इसका उपयोग निम्नलिखित तरीके से किया जा सकता है:

String s = stringList.stream().collect(Collectors.joining(" and ", "prefix_", "_suffix"))

Collectors.joining(CharSequence delimiter)विधि सिर्फ कॉल joining(delimiter, "", "")आंतरिक रूप से।


0

आप इसका उपयोग स्प्रिंग फ्रेमवर्क के स्ट्रिंगरिल्स से कर सकते हैं। मुझे पता है कि यह पहले ही उल्लेख किया गया है, लेकिन आप वास्तव में इस कोड को ले सकते हैं और यह तुरंत काम करता है, इसके लिए वसंत की आवश्यकता के बिना।

// from https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/util/StringUtils.java

/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
public class StringUtils {
    public static String collectionToDelimitedString(Collection<?> coll, String delim, String prefix, String suffix) {
        if(coll == null || coll.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        Iterator<?> it = coll.iterator();
        while (it.hasNext()) {
            sb.append(prefix).append(it.next()).append(suffix);
            if (it.hasNext()) {
                sb.append(delim);
            }
        }
        return sb.toString();
    }
}

-3

इसे इस्तेमाल करे:

java.util.Arrays.toString(anArray).replaceAll(", ", ",")
                .replaceFirst("^\\[","").replaceFirst("\\]$","");

1
शायद इसलिए क्योंकि प्रश्न एक सूची बनाम एक सरणी के उपयोग के लिए कहता है? कंधे उचकाने की क्रिया
निक Coelius

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