วิธีที่ดีที่สุดในการสร้างสตริงของรายการที่มีการคั่นใน Java คืออะไร?


317

ในขณะที่ทำงานในแอพพลิเคชั่น Java เมื่อเร็ว ๆ นี้ฉันจำเป็นต้องรวบรวมรายการค่าที่คั่นด้วยเครื่องหมายจุลภาคเพื่อส่งต่อไปยังบริการเว็บอื่นโดยไม่ทราบว่าจะมีองค์ประกอบกี่รายการล่วงหน้า สิ่งที่ดีที่สุดที่ฉันสามารถทำได้ด้วยการปิดส่วนหัวของฉันคือสิ่งนี้:

public String appendWithDelimiter( String original, String addition, String delimiter ) {
    if ( original.equals( "" ) ) {
        return addition;
    } else {
        return original + delimiter + addition;
    }
}

String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );

ฉันรู้ว่านี่ไม่ได้มีประสิทธิภาพมากนักเนื่องจากมีการสร้างสายอักขระอยู่ทั่วสถานที่ แต่ฉันก็ต้องการความชัดเจนมากกว่าการปรับให้เหมาะสม

ใน Ruby ฉันสามารถทำสิ่งนี้แทนซึ่งให้ความรู้สึกหรูหรามากกว่า:

parameterArray = [];
parameterArray << "elementName" if condition;
parameterArray << "anotherElementName" if anotherCondition;
parameterString = parameterArray.join(",");

แต่เนื่องจาก Java ขาดคำสั่งเข้าร่วมฉันจึงไม่สามารถเข้าใจสิ่งที่เทียบเท่าได้

ดังนั้นวิธีที่ดีที่สุดในการทำเช่นนี้ใน Java คืออะไร?


StringbBilder เป็นวิธีที่จะไป - java.lang.StringBuilder
Yusubov

สำหรับ Java 8 ให้ดูที่คำตอบนี้: stackoverflow.com/a/22577623/1115554
micha

คำตอบ:


542

Pre Java 8:

Apache คอมมอนส์ lang เป็นเพื่อนของคุณที่นี่ - มันให้วิธีการเข้าร่วมคล้ายกับที่คุณอ้างถึงใน Ruby:

StringUtils.join(java.lang.Iterable,char)


Java 8:

Java 8 ให้เข้าร่วมออกจากช่องทางและStringJoiner String.join()ตัวอย่างด้านล่างแสดงวิธีการใช้งาน:

StringJoiner

StringJoiner joiner = new StringJoiner(",");
joiner.add("01").add("02").add("03");
String joinedString = joiner.toString(); // "01,02,03"

String.join(CharSequence delimiter, CharSequence... elements))

String joinedString = String.join(" - ", "04", "05", "06"); // "04 - 05 - 06"

String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)

List<String> strings = new LinkedList<>();
strings.add("Java");strings.add("is");
strings.add("cool");
String message = String.join(" ", strings);
//message returned is: "Java is cool"

2
ฉันสงสัยว่า - สิ่งนี้คำนึงหรือไม่หากการแสดงสตริงของวัตถุในคอลเลกชันมีอักขระตัวคั่น?
GreenieMeanie

4
สิ่งที่ฉันกำลังค้นหา: StringUtils.join (java.util.Collection, String) จากแพ็กเกจ org.apache.commons.lang3.StringUtils ไฟล์ jar คือ commons-lang3-3.0.1.jar
Umar

108
บน Android คุณสามารถใช้ TextUtils.join () ได้เช่นกัน
James Wald

3
มันไม่ใช่วิธีที่ดีที่สุด มันมักจะเพิ่มตัวละครแม้ว่าวัตถุในคอลเลกชันเป็นโมฆะ / ว่างเปล่า มันสวยและสะอาด แต่บางครั้งมันก็จะพิมพ์ตัวคั่นคู่
Stephan Schielke

52

คุณสามารถเขียนวิธียูทิลิตี้สไตล์การเข้าร่วมขนาดเล็กที่ใช้กับ java.util.Lists

public static String join(List<String> list, String delim) {

    StringBuilder sb = new StringBuilder();

    String loopDelim = "";

    for(String s : list) {

        sb.append(loopDelim);
        sb.append(s);            

        loopDelim = delim;
    }

    return sb.toString();
}

จากนั้นใช้งานเช่น:

    List<String> list = new ArrayList<String>();

    if( condition )        list.add("elementName");
    if( anotherCondition ) list.add("anotherElementName");

    join(list, ",");

2
ทำไมคุณควรเขียนวิธีการของคุณเองถ้ามีอย่างน้อย 2 การใช้งาน (apache และฝรั่ง) มีอยู่แล้ว?
Timofey

29
สิ่งนี้อาจเป็นประโยชน์หากใครต้องการมีการพึ่งพาจากภายนอกน้อยลง
โทมัส Zumbrunn

2
ฉันชอบวิธีใช้ loopDelim แทนเงื่อนไข มันเป็นชนิดของการแฮ็ค แต่จะลบข้อความสั่งที่มีเงื่อนไขออกจากวงจร ฉันยังคงชอบใช้ตัววนซ้ำและเพิ่มองค์ประกอบแรกก่อนวัฏจักร แต่มันเป็นการแฮ็คที่ดีแน่นอน
Vlasec

คุณไม่สามารถเปลี่ยนList<String>intitializer เป็นIterator<?>และมีผลเหมือนกันได้หรือไม่?
k_g

@Tim Eg apache ไม่ข้ามสตริงว่าง
banterCZ


31

ห้องสมุดฝรั่งของ Googleมีcom.google.common.base.Joinerชั้นซึ่งจะช่วยแก้ปัญหางานดังกล่าว

ตัวอย่าง:

"My pets are: " + Joiner.on(", ").join(Arrays.asList("rabbit", "parrot", "dog")); 
// returns "My pets are: rabbit, parrot, dog"

Joiner.on(" AND ").join(Arrays.asList("field1=1" , "field2=2", "field3=3"));
// returns "field1=1 AND field2=2 AND field3=3"

Joiner.on(",").skipNulls().join(Arrays.asList("London", "Moscow", null, "New York", null, "Paris"));
// returns "London,Moscow,New York,Paris"

Joiner.on(", ").useForNull("Team held a draw").join(Arrays.asList("FC Barcelona", "FC Bayern", null, null, "Chelsea FC", "AC Milan"));
// returns "FC Barcelona, FC Bayern, Team held a draw, Team held a draw, Chelsea FC, AC Milan"

นี่คือบทความเกี่ยวกับฝรั่งของสาธารณูปโภคสตริง



20

คุณสามารถพูดคุยทั่วไปได้ แต่ไม่มีการเข้าร่วมใน Java อย่างที่คุณพูด

สิ่งนี้อาจทำงานได้ดีขึ้น

public static String join(Iterable<? extends CharSequence> s, String delimiter) {
    Iterator<? extends CharSequence> iter = s.iterator();
    if (!iter.hasNext()) return "";
    StringBuilder buffer = new StringBuilder(iter.next());
    while (iter.hasNext()) buffer.append(delimiter).append(iter.next());
    return buffer.toString();
}

ฉันเห็นด้วยกับคำตอบนี้ แต่ใครบางคนสามารถแก้ไขลายเซ็นเพื่อให้มันรับ Collection <String> แทนที่จะเป็น AbstractCollection <String> ส่วนที่เหลือของรหัสควรเหมือนกัน แต่ฉันคิดว่า AbstractCollection เป็นรายละเอียดการใช้งานที่ไม่สำคัญที่นี่
Outlaw Programmer

ยังดีกว่าใช้งานIterable<String>และใช้ความจริงที่ว่าคุณสามารถทำซ้ำได้ ในตัวอย่างของคุณคุณไม่จำเป็นต้องมีจำนวนรายการในคอลเลกชันดังนั้นจึงเป็นเรื่องทั่วไปมากขึ้น
Jason Cohen

1
หรือดียิ่งขึ้นให้ใช้ Iterable <? ขยาย Charsequence> และจากนั้นคุณสามารถยอมรับคอลเลกชันของ StringBuilders และ Strings และสตรีมและสิ่งอื่น ๆ ที่คล้ายสตริง :)
Jason Cohen

2
คุณต้องการที่จะใช้StringBuilderแทน พวกเขาเหมือนกันยกเว้นStringBufferให้ความปลอดภัยด้ายที่ไม่จำเป็น มีคนช่วยแก้ไขได้ไหม!
Casebash

1
รหัสนี้มีข้อผิดพลาดหลายประการ 1. CharSequence มีเงินทุน 2. s.iterator () ส่งคืน Iterator <? ขยาย CharSequence> 3. Iterable ไม่มีisEmpty()เมธอดใช้next()เมธอดแทน
Casebash

17

ใน Java 8 คุณสามารถทำสิ่งนี้เช่น:

list.stream().map(Object::toString)
        .collect(Collectors.joining(delimiter));

หากรายการมีค่าเป็นโมฆะคุณสามารถใช้:

list.stream().map(String::valueOf)
        .collect(Collectors.joining(delimiter))

มันยังรองรับคำนำหน้าและคำต่อท้าย:

list.stream().map(String::valueOf)
        .collect(Collectors.joining(delimiter, prefix, suffix));

15

ใช้วิธีการตามjava.lang.StringBuilder! ("ลำดับอักขระที่ไม่แน่นอน")

เช่นเดียวกับที่คุณพูดถึงสตริงที่เชื่อมโยงกันทั้งหมดกำลังสร้างสตริงทั้งหมด StringBuilderจะไม่ทำอย่างนั้น

ทำไมStringBuilderแทนStringBuffer? จากStringBuilderjavadoc:

หากเป็นไปได้ขอแนะนำให้ใช้คลาสนี้ในการกำหนดค่าตามความชอบกับ StringBuffer เนื่องจากจะเร็วกว่าในการนำไปใช้งานส่วนใหญ่


4
อ๋อ นอกจากนี้ StringBuffer ยังปลอดภัยสำหรับเธรดในขณะที่ StringBuilder ไม่ใช่
Jon Onstott

10

ฉันจะใช้ Google Collections มีสิ่งอำนวยความสะดวกเข้าร่วมที่ดี
http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/base/Join.html

แต่ถ้าฉันต้องการเขียนด้วยตัวเอง

package util;

import java.util.ArrayList;
import java.util.Iterable;
import java.util.Collections;
import java.util.Iterator;

public class Utils {
    // accept a collection of objects, since all objects have toString()
    public static String join(String delimiter, Iterable<? extends Object> objs) {
        if (objs.isEmpty()) {
            return "";
        }
        Iterator<? extends Object> iter = objs.iterator();
        StringBuilder buffer = new StringBuilder();
        buffer.append(iter.next());
        while (iter.hasNext()) {
            buffer.append(delimiter).append(iter.next());
        }
        return buffer.toString();
    }

    // for convenience
    public static String join(String delimiter, Object... objs) {
        ArrayList<Object> list = new ArrayList<Object>();
        Collections.addAll(list, objs);
        return join(delimiter, list);
    }
}

ฉันคิดว่ามันทำงานได้ดีขึ้นกับการรวบรวมวัตถุเนื่องจากตอนนี้คุณไม่ต้องแปลงวัตถุเป็นสตริงก่อนที่จะเข้าร่วม




3

คุณสามารถใช้StringBuilderชนิดของ Java สำหรับสิ่งนี้ นอกจากนี้ยังมีStringBufferแต่มันมีตรรกะความปลอดภัยหัวข้อพิเศษที่มักไม่จำเป็น


3

และน้อยที่สุด (ถ้าคุณไม่ต้องการรวม Apache Commons หรือ Gauva ในการอ้างอิงโครงการเพียงเพื่อการเข้าร่วมสตริง)

/**
 *
 * @param delim : String that should be kept in between the parts
 * @param parts : parts that needs to be joined
 * @return  a String that's formed by joining the parts
 */
private static final String join(String delim, String... parts) {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < parts.length - 1; i++) {
        builder.append(parts[i]).append(delim);
    }
    if(parts.length > 0){
        builder.append(parts[parts.length - 1]);
    }
    return builder.toString();
}

ใช้ delim แทน File.separator
Pradeep Kumar

3

ใช้ StringBuilder และคลาส Separator

StringBuilder buf = new StringBuilder();
Separator sep = new Separator(", ");
for (String each : list) {
    buf.append(sep).append(each);
}

ตัวคั่นล้อมตัวคั่น ตัวคั่นจะถูกส่งกลับโดยtoStringวิธีการของตัวคั่นยกเว้นในการโทรครั้งแรกที่ส่งกลับสตริงที่ว่างเปล่า!

ซอร์สโค้ดสำหรับคลาส Separator

public class Separator {

    private boolean skipFirst;
    private final String value;

    public Separator() {
        this(", ");
    }

    public Separator(String value) {
        this.value = value;
        this.skipFirst = true;
    }

    public void reset() {
        skipFirst = true;
    }

    public String toString() {
        String sep = skipFirst ? "" : value;
        skipFirst = false;
        return sep;
    }

}

สิ่งที่เกี่ยวกับการปรับเปลี่ยนSeparatorเพื่อที่จะใช้StringBuilderแทนการเรียงต่อกันStrings?
Mohamed Nuur

@Mohamed Separatorเพิ่งส่งคืนตัวคั่นมันไม่ได้เชื่อมสตริงตัวเอง
akuhn

คลาสนี้คืออะไรSeparator??? ทำไมไม่ลองใช้สตริงแบบง่าย ๆ .. ?!
maxxyme

2

ทำไมไม่เขียนวิธีการเข้าร่วม () ของคุณเอง? มันจะใช้เป็นคอลเลกชันพารามิเตอร์ของ Strings และสตริงตัวคั่น ภายในวิธีการวนซ้ำคอลเลกชันและสร้างผลลัพธ์ของคุณใน StringBuffer


2

หากคุณใช้ Spring MVC คุณสามารถลองทำตามขั้นตอนได้

import org.springframework.util.StringUtils;

List<String> groupIds = new List<String>;   
groupIds.add("a");    
groupIds.add("b");    
groupIds.add("c");

String csv = StringUtils.arrayToCommaDelimitedString(groupIds.toArray());

มันจะส่งผลให้ a,b,c


2

หากคุณกำลังใช้Eclipse คอลเลกชันคุณสามารถใช้หรือmakeString()appendString()

makeString()ส่งกลับเป็นตัวแทนเพื่อที่คล้ายกันStringtoString()

มันมีสามรูปแบบ

  • makeString(start, separator, end)
  • makeString(separator) ค่าเริ่มต้นเริ่มต้นและสิ้นสุดเป็นสตริงว่าง
  • makeString()ค่าเริ่มต้นตัวคั่นไปที่", "(จุลภาคและพื้นที่)

ตัวอย่างรหัส:

MutableList<Integer> list = FastList.newListWith(1, 2, 3);
assertEquals("[1/2/3]", list.makeString("[", "/", "]"));
assertEquals("1/2/3", list.makeString("/"));
assertEquals("1, 2, 3", list.makeString());
assertEquals(list.toString(), list.makeString("[", ", ", "]"));

appendString()คล้ายกับmakeString()แต่มันผนวกไปยังAppendable(ชอบStringBuilder) voidและเป็น มันมีสามรูปแบบเดียวกันโดยมีอาร์กิวเมนต์แรกเพิ่มเติมคือ Appendable

MutableList<Integer> list = FastList.newListWith(1, 2, 3);
Appendable appendable = new StringBuilder();
list.appendString(appendable, "[", "/", "]");
assertEquals("[1/2/3]", appendable.toString());

หากคุณไม่สามารถแปลงคอลเลกชันของคุณให้เป็นประเภทคอลเลกชัน Eclipse เพียงปรับใช้กับอะแดปเตอร์ที่เกี่ยวข้อง

List<Object> list = ...;
ListAdapter.adapt(list).makeString(",");

หมายเหตุ:ฉันเป็นคอมมิชชันสำหรับคอลเลกชัน Eclipse


2

Java 8 Native Type

List<Integer> example;
example.add(1);
example.add(2);
example.add(3);
...
example.stream().collect(Collectors.joining(","));

วัตถุที่กำหนดเองของ Java 8:

List<Person> person;
...
person.stream().map(Person::getAge).collect(Collectors.joining(","));

1

คุณควรใช้ a StringBuilderพร้อมกับappendวิธีการสร้างผลลัพธ์ของคุณ แต่ไม่เช่นนั้นจะเป็นวิธีแก้ปัญหาที่ดีตามที่ Java มีให้


1

ทำไมคุณไม่ทำใน Java เหมือนกับที่คุณทำในทับทิมนั่นคือการสร้างสตริงคั่นตัวคั่นหลังจากที่คุณเพิ่มชิ้นส่วนทั้งหมดลงในอาเรย์แล้ว?

ArrayList<String> parms = new ArrayList<String>();
if (someCondition) parms.add("someString");
if (anotherCondition) parms.add("someOtherString");
// ...
String sep = ""; StringBuffer b = new StringBuffer();
for (String p: parms) {
    b.append(sep);
    b.append(p);
    sep = "yourDelimiter";
}

คุณอาจต้องการย้ายที่วนซ้ำในวิธีการแยกต่างหากและยังใช้ StringBuilder แทน StringBuffer ...

แก้ไข : แก้ไขลำดับของการผนวก


ใช่ทำไมคุณถึงใช้ StringBuffer แทน StringBuilder (เหมือนที่คุณใช้ Java 1.5+) นอกจากนี้คุณยังมีส่วนต่อท้ายของวิธีที่ผิด
Tom Hawtin - tackline

1

ด้วยตัวแปร Java 5 args ดังนั้นคุณไม่ต้องยัดสตริงทั้งหมดลงในคอลเลกชันหรืออาร์เรย์อย่างชัดเจน:

import junit.framework.Assert;
import org.junit.Test;

public class StringUtil
{
    public static String join(String delim, String... strings)
    {
        StringBuilder builder = new StringBuilder();

        if (strings != null)
        {
            for (String str : strings)
            {
                if (builder.length() > 0)
                {
                    builder.append(delim).append(" ");
                }
                builder.append(str);
            }
        }           
        return builder.toString();
    }
    @Test
    public void joinTest()
    {
        Assert.assertEquals("", StringUtil.join(",", null));
        Assert.assertEquals("", StringUtil.join(",", ""));
        Assert.assertEquals("", StringUtil.join(",", new String[0]));
        Assert.assertEquals("test", StringUtil.join(",", "test"));
        Assert.assertEquals("foo, bar", StringUtil.join(",", "foo", "bar"));
        Assert.assertEquals("foo, bar, x", StringUtil.join(",", "foo", "bar", "x"));
    }
}

1

สำหรับผู้ที่อยู่ในบริบท Spring คลาสStringUtilsของพวกเขามีประโยชน์เช่นกัน:

มีทางลัดที่มีประโยชน์มากมายเช่น:

  • collectionToCommaDelimitedString (คอลเลกชันคอลเลกชัน)
  • collectionToDelimitedString (คอลเลกชันคอลเลกชัน delim สตริง)
  • arrayToDelimitedString (Object [] arr, String delim)

และอื่น ๆ อีกมากมาย.

สิ่งนี้มีประโยชน์หากคุณยังไม่ได้ใช้ Java 8 และคุณอยู่ในบริบทของ Spring อยู่แล้ว

ฉันชอบมันมากกว่า Apache Commons (แม้ว่าจะดีมากเช่นกัน) สำหรับการสนับสนุน Collection ซึ่งง่ายกว่าเช่นนี้:

// Encoding Set<String> to String delimited 
String asString = org.springframework.util.StringUtils.collectionToDelimitedString(codes, ";");

// Decoding String delimited to Set
Set<String> collection = org.springframework.util.StringUtils.commaDelimitedListToSet(asString);

0

คุณสามารถลองสิ่งนี้:

StringBuilder sb = new StringBuilder();
if (condition) { sb.append("elementName").append(","); }
if (anotherCondition) { sb.append("anotherElementName").append(","); }
String parameterString = sb.toString();

ดูเหมือนว่าจะมีเครื่องหมายจุลภาคหลงทางอยู่ท้ายสตริงซึ่งฉันหวังว่าจะหลีกเลี่ยง (แน่นอนว่าเมื่อคุณรู้ว่ามันอยู่ที่นั่นคุณก็สามารถตัดมันได้ แต่มันก็มีกลิ่นเล็กน้อยที่ไม่เหมาะสมเช่นกัน)
Sean McMains

0

ดังนั้นโดยทั่วไปบางสิ่งเช่นนี้:

public static String appendWithDelimiter(String original, String addition, String delimiter) {

if (original.equals("")) {
    return addition;
} else {
    StringBuilder sb = new StringBuilder(original.length() + addition.length() + delimiter.length());
        sb.append(original);
        sb.append(delimiter);
        sb.append(addition);
        return sb.toString();
    }
}

ปัญหาที่นี่คือเขาดูเหมือนจะเรียก appendWithDelimiter () จัดสรร การแก้ปัญหาควรอินสแตนซ์หนึ่งเดียว StringBuffer เดียวและทำงานกับอินสแตนซ์เดียวนั้น
Stu Thompson

0

ไม่ทราบว่านี่จะดีกว่านี้จริง ๆ หรืออย่างน้อยก็ใช้ StringBuilder ซึ่งอาจมีประสิทธิภาพมากกว่าเล็กน้อย

ด้านล่างเป็นวิธีการทั่วไปที่มากขึ้นถ้าคุณสามารถสร้างรายการพารามิเตอร์ก่อนที่จะทำการกำหนดพารามิเตอร์ใด ๆ

// Answers real question
public String appendWithDelimiters(String delimiter, String original, String addition) {
    StringBuilder sb = new StringBuilder(original);
    if(sb.length()!=0) {
        sb.append(delimiter).append(addition);
    } else {
        sb.append(addition);
    }
    return sb.toString();
}


// A more generic case.
// ... means a list of indeterminate length of Strings.
public String appendWithDelimitersGeneric(String delimiter, String... strings) {
    StringBuilder sb = new StringBuilder();
    for (String string : strings) {
        if(sb.length()!=0) {
            sb.append(delimiter).append(string);
        } else {
            sb.append(string);
        }
    }

    return sb.toString();
}

public void testAppendWithDelimiters() {
    String string = appendWithDelimitersGeneric(",", "string1", "string2", "string3");
}

0

วิธีการของคุณไม่เลวร้ายเกินไป แต่คุณควรใช้ StringBuffer แทนที่จะใช้เครื่องหมาย + + มีข้อเสียอย่างใหญ่หลวงที่อินสแตนซ์สตริงใหม่กำลังถูกสร้างขึ้นสำหรับการดำเนินการแต่ละครั้ง ยิ่งสตริงของคุณยาวเท่าไหร่ค่าใช้จ่ายก็จะยิ่งมากขึ้น ดังนั้นการใช้ StringBuffer ควรเป็นวิธีที่เร็วที่สุด:

public StringBuffer appendWithDelimiter( StringBuffer original, String addition, String delimiter ) {
        if ( original == null ) {
                StringBuffer buffer = new StringBuffer();
                buffer.append(addition);
                return buffer;
        } else {
                buffer.append(delimiter);
                buffer.append(addition);
                return original;
        }
}

หลังจากที่คุณสร้างสายอักขระของคุณเสร็จแล้วให้เรียก toString () บน StringBuffer ที่ส่งคืน


1
การใช้ StringBuffer ที่นี่จะทำให้ช้าลงโดยไม่มีเหตุผลที่ดี การใช้ตัวดำเนินการ + จะใช้ StringBuilder ที่เร็วขึ้นภายในเพื่อที่เขาจะไม่ชนะอะไรนอกจากความปลอดภัยของเธรดที่เขาไม่ต้องการโดยใช้ StringBuffer แทน
Fredrik

นอกจากนี้ ... คำสั่ง "+ มีข้อเสียอย่างใหญ่หลวงที่ว่าจะสร้างอินสแตนซ์สตริงใหม่สำหรับการดำเนินการแต่ละครั้ง" เป็นเท็จ คอมไพเลอร์จะสร้าง StringBuilder.append () โทรออกจากพวกเขา
Fredrik

0

แทนที่จะใช้การเรียงต่อสตริงคุณควรใช้ StringBuilder หากรหัสของคุณไม่ได้เป็นเกลียวและ StringBuffer ถ้ามันเป็น


0

คุณกำลังทำสิ่งนี้ซับซ้อนกว่านี้นิดหน่อย มาเริ่มกันที่ส่วนท้ายของตัวอย่าง:

String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );

ด้วยการเปลี่ยนแปลงเล็กน้อยในการใช้ StringBuilder แทนที่จะเป็น String สิ่งนี้จะกลายเป็น:

StringBuilder parameterString = new StringBuilder();
if (condition) parameterString.append("elementName").append(",");
if (anotherCondition) parameterString.append("anotherElementName").append(",");
...

เมื่อคุณทำเสร็จแล้ว (ฉันคิดว่าคุณต้องตรวจสอบเงื่อนไขอื่น ๆ ด้วย) ให้แน่ใจว่าคุณลบเครื่องหมายจุลภาคที่มีคำสั่งดังนี้:

if (parameterString.length() > 0) 
    parameterString.deleteCharAt(parameterString.length() - 1);

และสุดท้ายรับสตริงที่คุณต้องการด้วย

parameterString.toString();

คุณสามารถแทนที่ "," ในการโทรครั้งที่สองเพื่อต่อท้ายด้วยสตริงตัวคั่นทั่วไปที่สามารถตั้งค่าเป็นอะไรก็ได้ หากคุณมีรายการของสิ่งต่าง ๆ ที่คุณรู้ว่าคุณต้องผนวก (ไม่มีเงื่อนไข) คุณสามารถใส่รหัสนี้ในวิธีการที่ใช้รายการของสตริง


0
//Note: if you have access to Java5+, 
//use StringBuilder in preference to StringBuffer.  
//All that has to be replaced is the class name.  
//StringBuffer will work in Java 1.4, though.

appendWithDelimiter( StringBuffer buffer, String addition, 
    String delimiter ) {
    if ( buffer.length() == 0) {
        buffer.append(addition);
    } else {
        buffer.append(delimiter);
        buffer.append(addition);
    }
}


StringBuffer parameterBuffer = new StringBuffer();
if ( condition ) { 
    appendWithDelimiter(parameterBuffer, "elementName", "," );
}
if ( anotherCondition ) {
    appendWithDelimiter(parameterBuffer, "anotherElementName", "," );
}

//Finally, to return a string representation, call toString() when returning.
return parameterBuffer.toString(); 

0

ดังนั้นสองสิ่งที่คุณอาจทำเพื่อให้ได้ความรู้สึกที่ดูเหมือนว่าคุณกำลังมองหา:

1) ขยายรายการคลาส - และเพิ่มวิธีการเข้าร่วม วิธีการเข้าร่วมจะทำการเชื่อมโยงและเพิ่มตัวคั่น (ซึ่งอาจเป็นพารามิเตอร์ของวิธีการรวม)

2) ดูเหมือนว่า Java 7 กำลังจะเพิ่มวิธีการขยายไปยัง java - ซึ่งช่วยให้คุณเพียงแค่แนบวิธีการเฉพาะในชั้นเรียน: เพื่อให้คุณสามารถเขียนวิธีการเข้าร่วมที่และเพิ่มเป็นวิธีการขยายรายการหรือแม้แต่ ชุด

โซลูชันที่ 1 น่าจะเป็นสิ่งที่เหมือนจริงเพียงอย่างเดียวตอนนี้เนื่องจาก Java 7 ยังไม่ออก :) แต่ควรใช้งานได้ดี

หากต้องการใช้ทั้งสองอย่างนี้คุณเพียงแค่เพิ่มรายการทั้งหมดของคุณลงในรายการหรือคอลเล็กชันตามปกติแล้วเรียกวิธีการที่กำหนดเองใหม่เพื่อ 'เข้าร่วม'

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.