在Java中使用分隔符(与split相反)将数组元素连接起来的快捷方法
看到相关的.NET问题
我正在寻找一种快速而简单的方法来完成与split相反的操作,以使得["a","b","c"]
变成"a,b,c"
迭代一个数组需要添加一个条件(如果这不是最后一个元素,请添加分隔符)或使用子串删除最后一个分隔符。
我确定有一个认证的,有效的方法来做到这一点(Apache Commons?)
你喜欢在你的项目中做什么?
使用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);
如果你在Android上,你可以TextUtils.join(delimiter, tokens)
我更喜欢Google Collections通过Apache的StringUtils来解决这个问题:
Joiner.on(separator).join(array)
与StringUtils相比,Joiner API有一个流畅的设计,并且更灵活一点,例如null
元素可以被跳过,或者被一个占位符替代。 此外, Joiner
还有一个功能,用键和值之间的分隔符来连接地图。
Apache Commons Lang确实有一个StringUtils.join
方法,它将String
数组与指定的分隔符连接在一起。
例如:
String[] s = new String[] {"a", "b", "c"}; String joined = StringUtils.join(s, ","); // "a,b,c"
但是,我怀疑,正如你所提到的那样,在上述方法的实际实现中必须有某种条件或子串处理。
如果我要执行String
加入,并没有任何其他理由使用Commons Lang,我可能会自己推出,以减少对外部库的依赖的数量。
没有任何第三方的快速简单的解决方案包括。
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(); }
“我确信有一个经过认证的,有效的方法来做到这一点(Apache Commons?)”
是的,显然是这样
StringUtils.join(array, separator)
您可以使用正则表达式替换和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(", ", "," );
正则表达式非常强大,特别是String方法“replaceFirst”和“replaceAll”。 给他们一个尝试。
更简单的,你可以使用数组,所以你会得到一个字符串与数组的值分隔的一个“,”
String concat = Arrays.toString(myArray);
所以你最终会得到这个:concat =“[a,b,c]”
更新
然后,您可以使用Jeff所建议的子字符串来删除括号
concat = concat.substring(1, concat.length() -1);
所以你最终concat =“a,b,c”
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(","));
所有这些其他的答案包括运行时开销…就像使用ArrayList.toString()。replaceAll(…)这是非常浪费。
我会给你零开销的最佳算法; 它看起来不像其他选项那样漂亮,但是在内部,这就是他们正在做的事情(在其他一些隐藏的检查,多个数组分配以及其他方面)之后。
既然您已经知道您正在处理字符串,您可以通过手动执行所有操作来保存大量的数组分配。 这并不美观,但是如果您跟踪其他实现所做的实际方法调用,则会看到它具有最少的运行时间可能性。
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); }
它在StringUtils中:
这个选项是快速和明确的:
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); }
这个小功能总是派上用场。
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(); }
自从Java 1.0以来,我采用的方法已经发展了,以提供可读性并保持合理的选项,以便与旧Java版本向后兼容,同时还提供了方法签名,这些方法签名是来自apache commons-lang的替代方法。 出于性能方面的原因,我可以看到一些使用Arrays.asList的可能的反对意见,但是我更喜欢帮助者方法,它们具有合理的默认值,而不需要重复执行实际工作的方法。 这种方法为在调用之前不需要数组/列表转换的可靠方法提供了适当的入口点。
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(); }
public String join(String[] str, String separator){ String retval = ""; for (String s: str){ retval+= separator + s;} return retval.replaceFirst(separator, ""); }