一种逆转java String.split() 效果的方法? [复制]
Posted
技术标签:
【中文标题】一种逆转java String.split() 效果的方法? [复制]【英文标题】:A method to reverse effect of java String.split()? [duplicate] 【发布时间】:2010-10-22 02:37:53 【问题描述】:我正在寻找一种将字符串数组组合成分隔符的方法 细绳。与 split() 相反。
在我自己写之前想问问论坛(因为JDK什么都有)
【问题讨论】:
只需遍历数组并将元素连接到 StringBuilder 中。 ***.com/questions/63150/…、***.com/questions/448320/…、***.com/questions/205555/…、***.com/questions/58431/… 和其他几个的副本。 谢谢。我确实写过这样的方法,但是在过去多次重新发明***之后,然后发现jdk已经有了它......好吧,认为它是愤怒的帖子.. Phil 你只能估计,如果输入被这样的正则表达式分割:s = "foo:bar,baz".split ("[:,]")
请参阅下面@DenTheMan 的回答 Arrays.toString(Object[])
【参考方案1】:
据我所知,JDK 中没有用于此的方法。 Apache Commons Lang 在 StringUtils
类中有各种重载的 join()
方法,可以做你想做的事。
【讨论】:
对于未来的读者:Java 8 有一个 String.join() 方法。【参考方案2】:至少从 2009 年开始就有一个开放的功能请求。总而言之,它将成为 JDK 8 的 java.util.StringJoiner 类功能的一部分。 http://download.java.net/lambda/b81/docs/api/java/util/StringJoiner.html
如果您有兴趣,这里是 Oracle 问题。 http://bugs.sun.com/view_bug.do?bug_id=5015163
这是一个字符串数组上的新 JDK 8 StringJoiner 示例
String[] a = new String[]"first","second","third";
StringJoiner sj = new StringJoiner(",");
for(String s:a) sj.add(s);
System.out.println(sj); //first,second,third
String 中的实用方法使这更加简单:
String s = String.join(",", stringArray);
【讨论】:
【参考方案3】:您可以从 Arrays
实用程序包中偷偷使用此功能。
import java.util.Arrays;
...
String delim = ":",
csv_record = "Field0:Field1:Field2",
fields[] = csv_record.split(delim);
String rebuilt_record = Arrays.toString(fields)
.replace(", ", delim)
.replaceAll("[\\[\\]]", "");
【讨论】:
有点晚了,但这听起来通常是个坏主意,除非您绝对确定字符串中永远不会有 ', '。然后它可能远没有效率。【参考方案4】:我得到了下面的例子here
/*
7) Join Strings using separator >>>AB$#$CD$#$EF
*/
import org.apache.commons.lang.StringUtils;
public class StringUtilsTrial
public static void main(String[] args)
// Join all Strings in the Array into a Single String, separated by $#$
System.out.println("7) Join Strings using separator >>>"
+ StringUtils.join(new String[] "AB", "CD", "EF" , "$#$"));
【讨论】:
【参考方案5】:Google 还在他们的 Google Collections 库中提供了一个 joiner 类:
Joiner API
Google Collections
【讨论】:
我总是更喜欢 google apis 而不是 apache.commons。谢谢【参考方案6】:DZone Snippets 上有几个示例,如果您想推出自己的与集合一起使用的示例。例如:
public static String join(AbstractCollection<String> s, String delimiter)
if (s == null || s.isEmpty()) return "";
Iterator<String> iter = s.iterator();
StringBuilder builder = new StringBuilder(iter.next());
while( iter.hasNext() )
builder.append(delimiter).append(iter.next());
return builder.toString();
【讨论】:
我倾向于省略空检查,因为行为将是相同的,为什么在特殊情况下使代码复杂化?另一方面,可能需要进行空检查。 @Carl:我完全同意你的空检查并补充说。检查空集合允许函数跳过不必要的创建迭代器和字符串缓冲区,所以我把它留在里面。 您应该使用 StringBuilder 而不是 StringBuffer,因为 StringBuffer 会增加同步开销。您不需要同步方法变量(因为只有一个线程会使用它)。 您的连接方法应该接受 Collection,而不是 AbstractCollection。更好的是,它可以接受 Iterable,这使得它更通用。 @Steve:其中任何一个都可以接受。您可以根据需要使其抽象或具体。在我链接到的页面上有一个稍后的示例,它接受 Iterable。【参考方案7】:如果你有一个 int[],Arrays.toString()
是最简单的方法。
【讨论】:
实际上这也适用于 String[],使用 Arrays.toString(Object[]) 从 Java 1.5 开始可用,该版本于 2004 年发布 eons 在问题出现之前张贴。这是正确的答案,如果您不介意前缀“[”和后缀“]”。【参考方案8】:根据之前的所有答案:
public static String join(Iterable<? extends Object> elements, CharSequence separator)
StringBuilder builder = new StringBuilder();
if (elements != null)
Iterator<? extends Object> iter = elements.iterator();
if(iter.hasNext())
builder.append( String.valueOf( iter.next() ) );
while(iter.hasNext())
builder
.append( separator )
.append( String.valueOf( iter.next() ) );
return builder.toString();
【讨论】:
我认为这是更好的方法,简单高效。还需要提到的是,apache 使用一个简单的 for 和 if inside,而 openjdk8 做一些类似你的事情,但在分开的方法中。 您会很高兴知道 Java 8 现在允许您使用内置的String.join()
方法做到这一点。【参考方案9】:
对于 android:在 android.text.TextUtils 有方法:
public static String join (CharSequence delimiter, Iterable tokens)
public static String join (CharSequence delimiter, Object[] tokens)
返回一个字符串,其中包含由分隔符连接的标记。
tokens -- 要加入的数组对象。字符串将通过调用 object.toString() 从对象中形成。
【讨论】:
【参考方案10】:自从 JDK8 以来,我非常喜欢 Streams 和 Lambdas,所以我建议:
public static String join( String delimiter, String[] array )
return Arrays.asList( array ).stream().collect( Collectors.joining( delimiter ) );
【讨论】:
【参考方案11】:为了完整起见,我想补充一点,您一般不能反转 String#split,因为它接受正则表达式。
"hello__world".split("_+");
收益 ["hello", "world"]
."hello_world".split("_+");
收益 ["hello", "world"]
.
这些从不同的起点产生相同的结果。分裂不是一对一的操作,因此是不可逆的。
这就是说,如果您假设您的参数是固定字符串,而不是正则表达式,那么您当然可以使用许多发布的答案之一来做到这一点。
【讨论】:
【参考方案12】:这个也不错:
public static String join(String delimitor,String ... subkeys)
String result = null;
if(null!=subkeys && subkeys.length>0)
StringBuffer joinBuffer = new StringBuffer(subkeys[0]);
for(int idx=1;idx<subkeys.length;idx++)
joinBuffer.append(delimitor).append(subkeys[idx]);
result = joinBuffer.toString();
return result;
【讨论】:
@allyourcode 我认为StringBuffer
的使用避免了Schlemiel 问题link
+1 指向 Schlemiel 算法!【参考方案13】:
这是我写的:
public static String join(Collection<String> col, String delim)
StringBuilder sb = new StringBuilder();
Iterator<String> iter = col.iterator();
if (iter.hasNext())
sb.append(iter.next());
while (iter.hasNext())
sb.append(delim);
sb.append(iter.next());
return sb.toString();
JSP 不支持Collection
,所以对于 TLD,我写道:
public static String join(List<?> list, String delim)
int len = list.size();
if (len == 0)
return "";
StringBuilder sb = new StringBuilder(list.get(0).toString());
for (int i = 1; i < len; i++)
sb.append(delim);
sb.append(list.get(i).toString());
return sb.toString();
并放入.tld
文件:
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
<function>
<name>join</name>
<function-class>com.core.util.ReportUtil</function-class>
<function-signature>java.lang.String join(java.util.List, java.lang.String)</function-signature>
</function>
</taglib>
并在 JSP 文件中将其用作:
<%@taglib prefix="funnyFmt" uri="tag:com.core.util,2013:funnyFmt"%>
$funnyFmt:join(books, ", ")
【讨论】:
【参考方案14】:下面的代码给出了一个基本的想法。虽然这不是最好的解决方案。
public static String splitJoin(String sourceStr, String delim,boolean trim,boolean ignoreEmpty)
return join(Arrays.asList(sourceStr.split(delim)), delim, ignoreEmpty);
public static String join(List<?> list, String delim, boolean ignoreEmpty)
int len = list.size();
if (len == 0)
return "";
StringBuilder sb = new StringBuilder(list.get(0).toString());
for (int i = 1; i < len; i++)
if (ignoreEmpty && !StringUtils.isBlank(list.get(i).toString()))
sb.append(delim);
sb.append(list.get(i).toString().trim());
return sb.toString();
【讨论】:
【参考方案15】:如果您使用 jdk8,请参阅 @Nathaniel Johnson 的 answer,因为这样会更好。
我认为这里的许多答案都很复杂或不易阅读。既然分支预测如此高效,为什么你干脆不使用 if 语句?
public static String join(List<String> fooList)
if (fooList.isEmpty()) return "";
StringBuilder sb = null;
for (String element : fooList)
if (sb == null)
sb = new StringBuilder();
else
sb.append(", ");
sb.append(element);
return sb.toString();
应该提到的是,Apache 使用了一个简单的 for 循环,其中有一个 if 语句,就像这样(它使用数组作为索引来知道第一个元素),而 openjdk 8 也是这样做的,但在分开的方法调用中而不是一个简单的循环。
【讨论】:
【参考方案16】:我更喜欢这个:
public String join(Collection<String> strCollection, String delimiter)
String joined = "";
int noOfItems = 0;
for (String item : strCollection)
joined += item;
if (++noOfItems < strCollection.size())
joined += delimiter;
return joined;
这是迄今为止我找到的最简洁的解决方案。 (不用担心使用原始 String 对象而不是 StringBuilder。现代 Java 编译器无论如何都使用 StringBuilder,但这段代码更具可读性)。
【讨论】:
这受到 Schlemeil 问题的影响:en.wikipedia.org/wiki/Schlemiel_the_Painter's_algorithm @allyourcode 我以前从未听说过这个问题,谢谢你的链接! @allyourcode 很幸运,如今编译器为像 Schlemeil 这样的笨蛋“移动了油漆罐”。以上是关于一种逆转java String.split() 效果的方法? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
Brief introduction to Java String Split 简单介绍下Java String Split