我有以下字符串:
A:B:1111;domain:80;a;b
A
是可选的,因此B:1111;domain:80;a;b
也是有效输入
:80
也是可选的,因此B:1111;domain;a;b
或:1111;domain;a;b
也是有效输入
我想要的是以String[]
结尾:
s[0] = "A";
s[1] = "B";
s[2] = "1111";
s[3] = "domain:80"
s[4] = "a"
s[5] = "b"
我这样做了如下:
List<String> tokens = new ArrayList<String>();
String[] values = s.split(";");
String[] actions = values[0].split(":");
for(String a:actions){
tokens.add(a);
}
//Start from 1 to skip A:B:1111
for(int i = 1; i < values.length; i++){
tokens.add(values[i]);
}
String[] finalResult = tokens.toArray();
我想知道有更好的方法吗?我怎么能更有效地做到这一点?
答案 0 :(得分:2)
这里的效率问题并不多,我看到的只是线性。
无论如何,你可以使用正则表达式或手动标记器。
您可以避开该列表。您知道values
和actions
的长度,因此您可以
String[] values = s.split(";");
String[] actions = values[0].split(":");
String[] result = new String[actions.length + values.length - 1];
System.arraycopy(actions, 0, result, 0, actions.legnth);
System.arraycopy(values, 1, result, actions.length, values.length - 1);
return result;
除非你坚持自己实施split
,否则应该合理有效。
未经测试的低级方法(确保在使用前进行单元测试和基准测试):
// Separator characters, as char, not string.
final static int s1 = ':';
final static int s2 = ';';
// Compute required size:
int components = 1;
for(int p = Math.min(s.indexOf(s1), s.indexOf(s2));
p < s.length() && p > -1;
p = s.indexOf(s2, p+1)) {
components++;
}
String[] result = new String[components];
// Build result
int in=0, i=0, out=Math.min(s.indexOf(s1), s.indexOf(s2));
while(out < s.length() && out > -1) {
result[i] = s.substring(in, out);
i++;
in = out + 1;
out = s.indexOf(s2, in);
}
assert(i == result.length - 1);
result[i] = s.substring(in, s.length());
return result;
注意:此代码以疯狂的方式进行优化,仅在第一个组件中考虑:
。处理最后一个组件有点棘手,因为out
的值为-1
。
我通常不使用最后一种方法,除非性能和内存非常重要。最有可能的是它仍然存在一些漏洞,而且代码相当难以理解,特别是与上面的相比。
答案 1 :(得分:1)
通过对可接受字符的一些假设,这个正则表达式提供了验证以及分成你想要的组。
Pattern p = Pattern.compile("^((.+):)?(.+):(\\d+);(.+):(\\d+);(.+);(.+)$");
Matcher m = p.matcher("A:B:1111;domain:80;a;b");
if(m.matches())
{
for(int i = 0; i <= m.groupCount(); i++)
System.out.println(m.group(i));
}
m = p.matcher("B:1111;domain:80;a;b");
if(m.matches())
{
for(int i = 0; i <= m.groupCount(); i++)
System.out.println(m.group(i));
}
给出:
A:B:1111;domain:80;a;b // ignore this
A: // ignore this
A // This is the optional A, check for null
B
1111
domain
80
a
b
和
B:1111;domain:80;a;b // ignore this
null // ignore this
null // This is the optional A, check for null
B
1111
domain
80
a
b
答案 2 :(得分:0)
String str = "A:B:1111;domain:80;a;b";
String[] temp;
/* delimiter */
String delimiter = ";";
/* given string will be split by the argument delimiter provided. */
temp = str.split(delimiter);
/* print substrings */
for(int i =0; i < temp.length ; i++)
System.out.println(temp[i]);
答案 3 :(得分:0)
除非这是您的代码中的瓶颈,并且您已经确认不要太担心效率,因为这里的逻辑是合理的。您可以避免创建临时数组列表,而是直接创建数组,因为您知道所需的大小。
答案 4 :(得分:0)
如果你想保持域和端口在一起,那么我相信你需要你需要两个分裂。你可以用一些正则表达式魔法来做到这一点,但我怀疑你会从中看到任何真正的性能提升。
如果您不介意拆分域和端口,那么:
String s= "A:B:1111;domain:80;a;b";
List<String> tokens = new ArrayList<String>();
String[] values = s.split(";|:");
for(String a : values){
tokens.add(a);
}