在Java应用程序中工作时,我最近需要组装一个以逗号分隔的值列表,以传递给另一个Web服务,而无需事先知道有多少元素.我能想出的最好的东西是这样的:
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中执行此操作的最佳方法是什么?
Apache的commons lang是你的朋友 - 它提供了一个非常类似于你在Ruby中引用的连接方法:
StringUtils.join(java.lang.Iterable,char)
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)
Liststrings = new LinkedList<>(); strings.add("Java");strings.add("is"); strings.add("cool"); String message = String.join(" ", strings); //message returned is: "Java is cool"
您可以编写一个适用于java.util.Lists的小型连接样式实用程序方法
public static String join(Listlist, String delim) { StringBuilder sb = new StringBuilder(); String loopDelim = ""; for(String s : list) { sb.append(loopDelim); sb.append(s); loopDelim = delim; } return sb.toString(); }
然后像这样使用它:
Listlist = new ArrayList (); if( condition ) list.add("elementName"); if( anotherCondition ) list.add("anotherElementName"); join(list, ",");
在Android的情况下,来自commons的StringUtils类不可用,所以为此我使用了
android.text.TextUtils.join(CharSequence delimiter, Iterable tokens)
http://developer.android.com/reference/android/text/TextUtils.html
在谷歌的番石榴库具有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"
这是一篇关于Guava的字符串实用程序的文章.
在Java 8中,您可以使用String.join()
:
Listlist = Arrays.asList("foo", "bar", "baz"); String joined = String.join(" and ", list); // "foo and bar and baz"
还要看一下Stream API示例的答案.
您可以对它进行概括,但正如您所说,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(); }
使用基于的方法java.lang.StringBuilder
!("一个可变的字符序列.")
就像你提到的那样,所有这些字符串连接都在创建字符串. StringBuilder
不会这样做.
为什么StringBuilder
而不是StringBuffer
?来自StringBuilder
javadoc:
在可能的情况下,建议首先使用此类优先于StringBuffer,因为在大多数实现中它会更快.
在Java 8中你可以这样做:
list.stream().map(Object::toString)
.collect(Collectors.joining(delimiter));
如果list有空值,你可以使用:
list.stream().map(String::valueOf)
.collect(Collectors.joining(delimiter))
我会使用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
我认为它对象集合更好用,因为现在你不必在加入它们之前将对象转换为字符串.
Apache commons StringUtils类有一个join方法.
stringCollection.stream().collect(Collectors.joining(", "));