What's the best way to build a string of delimited items in Java?

前端 未结 30 2198
耶瑟儿~
耶瑟儿~ 2020-11-22 05:36

While working in a Java app, I recently needed to assemble a comma-delimited list of values to pass to another web service without knowing how many elements there would be i

相关标签:
30条回答
  • 2020-11-22 06:34

    You're making this a little more complicated than it has to be. Let's start with the end of your example:

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

    With the small change of using a StringBuilder instead of a String, this becomes:

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

    When you're done (I assume you have to check a few other conditions as well), just make sure you remove the tailing comma with a command like this:

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

    And finally, get the string you want with

    parameterString.toString();
    

    You could also replace the "," in the second call to append with a generic delimiter string that can be set to anything. If you have a list of things you know you need to append (non-conditionally), you could put this code inside a method that takes a list of strings.

    0 讨论(0)
  • 2020-11-22 06:35

    Use StringBuilder and class Separator

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

    Separator wraps a delimiter. The delimiter is returned by Separator's toString method, unless on the first call which returns the empty string!

    Source code for class 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;
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 06:35

    With Java 5 variable args, so you don't have to stuff all your strings into a collection or array explicitly:

    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"));
        }
    }
    
    0 讨论(0)
  • 2020-11-22 06:35

    Instead of using string concatenation, you should use StringBuilder if your code is not threaded, and StringBuffer if it is.

    0 讨论(0)
  • 2020-11-22 06:36

    I would use Google Collections. There is a nice Join facility.
    http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/base/Join.html

    But if I wanted to write it on my own,

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

    I think it works better with an object collection, since now you don't have to convert your objects to strings before you join them.

    0 讨论(0)
  • 2020-11-22 06:37

    In the case of Android, the StringUtils class from commons isn't available, so for this I used

    android.text.TextUtils.join(CharSequence delimiter, Iterable tokens)
    

    http://developer.android.com/reference/android/text/TextUtils.html

    0 讨论(0)
提交回复
热议问题