在Java中使用分隔符(与分割相反)连接数组元素的快速简便方法

看到# EYZ0

我正在寻找一种快速和简单的方法来做完全相反的分裂 因此它将导致["a","b","c"]变成"a,b,c"

遍历数组需要添加一个条件(如果这不是最后一个元素,则添加分隔符)或使用substring删除最后一个分隔符。

我相信有一种经过认证的、有效的方法来做到这一点(Apache Commons?)

你喜欢在你的项目中怎么做?

638337 次浏览

“我相信有一种经过认证的、有效的方法来做到这一点(Apache Commons?)”

是的,很明显

StringUtils.join(array, separator)

http://www.java2s.com/Code/JavaAPI/org.apache.commons.lang/StringUtilsjoinObjectarrayStringseparator.htm

Apache Commons Lang确实有一个StringUtils.join方法,它将String数组与指定的分隔符连接在一起。

例如:

String[] s = new String[] {"a", "b", "c"};
String joined = StringUtils.join(s, ",");  // "a,b,c"

然而,正如您所提到的,我怀疑在上述方法的实际实现中一定存在某种条件或子字符串处理。

如果我要执行String连接,并且没有任何其他使用Commons Lang的原因,我可能会使用自己的连接,以减少对外部库的依赖数量。

对于这个特定的问题,我更喜欢番石榴而不是Apache StringUtils:

Joiner.on(separator).join(array)

与StringUtils相比,Joiner API具有流畅的设计,并且更加灵活,例如null元素可以被跳过或被占位符取代。此外,Joiner还有一个特性,用于在键和值之间使用分隔符连接映射。

你可以用正则表达式来使用replace和replaceAll。

String[] strings = {"a", "b", "c"};


String result = Arrays.asList(strings).toString().replaceAll("(^\\[|\\]$)", "").replace(", ", ",");

因为Arrays.asList().toString()生成:"[a, b, c]",所以我们执行replaceAll来删除第一个和最后一个括号,然后(可选地)您可以更改","序列为","(您的新分隔符)。

精简版(字符数更少):

String[] strings = {"a", "b", "c"};


String result = ("" + Arrays.asList(strings)).replaceAll("(^.|.$)", "").replace(", ", "," );

正则表达式非常强大,特别是字符串方法“replaceFirst”和“replaceAll”。试一试吧。

所有这些其他答案都包括运行时开销……比如使用ArrayList.toString(). replaceall(…),这是非常浪费的。

我会给你零开销的最佳算法; 它看起来不像其他选项那么漂亮,但在内部,这是它们都在做的事情(在成堆的其他隐藏检查,多个数组分配和其他crud之后)

因为您已经知道您正在处理字符串,所以您可以通过手动执行所有操作来节省大量的数组分配。这并不漂亮,但如果跟踪其他实现所执行的实际方法调用,您将看到它的运行时开销可能最少。

public static String join(String separator, String ... values) {
if (values.length==0)return "";//need at least one element
//all string operations use a new array, so minimize all calls possible
char[] sep = separator.toCharArray();


// determine final size and normalize nulls
int totalSize = (values.length - 1) * sep.length;// separator size
for (int i = 0; i < values.length; i++) {
if (values[i] == null)
values[i] = "";
else
totalSize += values[i].length();
}


//exact size; no bounds checks or resizes
char[] joined = new char[totalSize];
int pos = 0;
//note, we are iterating all the elements except the last one
for (int i = 0, end = values.length-1; i < end; i++) {
System.arraycopy(values[i].toCharArray(), 0,
joined, pos, values[i].length());
pos += values[i].length();
System.arraycopy(sep, 0, joined, pos, sep.length);
pos += sep.length;
}
//now, add the last element;
//this is why we checked values.length == 0 off the hop
System.arraycopy(values[values.length-1].toCharArray(), 0,
joined, pos, values[values.length-1].length());


return new String(joined);
}

一个快速和简单的解决方案,没有任何第三方包括。

public static String strJoin(String[] aArr, String sSep) {
StringBuilder sbStr = new StringBuilder();
for (int i = 0, il = aArr.length; i < il; i++) {
if (i > 0)
sbStr.append(sSep);
sbStr.append(aArr[i]);
}
return sbStr.toString();
}

在Java 1.8中有一个新的StringJoiner类 -所以不需要Guava或Apache Commons:

String str = new StringJoiner(",").add("a").add("b").add("c").toString();

或者直接使用新流api的集合:

String str = Arrays.asList("a", "b", "c").stream().collect(Collectors.joining(","));

这个小函数总是会派上用场。

public static String join(String[] strings, int startIndex, String separator) {
StringBuffer sb = new StringBuffer();
for (int i=startIndex; i < strings.length; i++) {
if (i != startIndex) sb.append(separator);
sb.append(strings[i]);
}
return sb.toString();
}

这个选项是快速和清晰的:

  public static String join(String separator, String... values) {
StringBuilder sb = new StringBuilder(128);
int end = 0;
for (String s : values) {
if (s != null) {
sb.append(s);
end = sb.length();
sb.append(separator);
}
}
return sb.substring(0, end);
}

更简单的是,你可以使用数组,所以你会得到一个字符串,数组的值由","隔开

String concat = Arrays.toString(myArray);

所以你会得到这样的结果:concat = "[a,b,c]"

更新

然后,您可以使用Jeff建议的子字符串来消除括号

concat = concat.substring(1, concat.length() -1);

所以你得到concat = "a,b,c"

如果你想使用Kotlin:

 val concat = myArray.joinToString(separator = ",") //"a,b,c"

如果你使用的是Android,你可以TextUtils.join(delimiter, tokens)

public String join(String[] str, String separator){
String retval = "";
for (String s: str){ retval+= separator + s;}
return retval.replaceFirst(separator, "");
}

使用Java 8,你可以用一种非常干净的方式做到这一点:

String.join(delimiter, elements);

这有三种方式:

1)直接指定要素

String joined1 = String.join(",", "a", "b", "c");

2)使用数组

String[] array = new String[] { "a", "b", "c" };
String joined2 = String.join(",", array);

3)使用可迭代对象

List<String> list = Arrays.asList(array);
String joined3 = String.join(",", list);

我所采用的方法自Java 1.0以来一直在发展,以提供可读性并维护与旧Java版本向后兼容的合理选项,同时还提供了方法签名,这些方法签名是apache common -lang中的方法签名的临时替代品。出于性能原因,我可以看到一些可能反对使用数组的理由。但我更喜欢具有合理默认值的辅助方法,而不会重复执行实际工作的一个方法。这种方法为可靠的方法提供了适当的入口点,该方法不需要在调用之前进行数组/列表转换。

Java版本兼容性的可能变化包括用StringBuffer (Java 1.0)代替StringBuilder (Java 1.5),切换出Java 1.5迭代器,并从集合(Java 1.2)中删除通用通配符(Java 1.5)。如果想进一步提高向后兼容性,可以删除使用Collection的方法,并将逻辑移到基于数组的方法中。

public static String join(String[] values)
{
return join(values, ',');
}


public static String join(String[] values, char delimiter)
{
return join(Arrays.asList(values), String.valueOf(delimiter));
}


// To match Apache commons-lang: StringUtils.join(values, delimiter)
public static String join(String[] values, String delimiter)
{
return join(Arrays.asList(values), delimiter);
}


public static String join(Collection<?> values)
{
return join(values, ',');
}


public static String join(Collection<?> values, char delimiter)
{
return join(values, String.valueOf(delimiter));
}


public static String join(Collection<?> values, String delimiter)
{
if (values == null)
{
return new String();
}


StringBuffer strbuf = new StringBuffer();


boolean first = true;


for (Object value : values)
{
if (!first) { strbuf.append(delimiter); } else { first = false; }
strbuf.append(value.toString());
}


return strbuf.toString();
}