【问题标题】:What is a good way to split strings here?在这里拆分字符串的好方法是什么?
【发布时间】:2012-05-24 01:09:06
【问题描述】:

我有以下字符串:
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();

我想知道有没有更好的方法来做到这一点?我还能如何更有效地做到这一点?

【问题讨论】:

  • 您是否尝试过:s.split("[;:]") 此正则表达式拆分为 ';' 的字符或“:”
  • 域名后面总是跟80 吗?
  • @codaddict:不,这也是可选的
  • 另一种方法是使用正则表达式,但我非常怀疑您是否可以做任何比您上面所做的更有效的事情。

标签: java regex string optimization


【解决方案1】:

这里没有太多效率问题,我看到的只是线性。

无论如何,您可以使用正则表达式或手动分词器。

你可以避开这个列表。你知道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。

我通常不使用最后一种方法,除非性能和内存非常重要。很可能它仍然存在一些错误,并且代码相当不可读,尤其是与上面的代码相比。

【讨论】:

    【解决方案2】:

    通过对可接受字符的一些假设,此正则表达式提供验证以及拆分为您想要的组。

    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
    

    【讨论】:

      【解决方案3】:

      你可以做类似的事情

      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]);
      

      【讨论】:

        【解决方案4】:

        除非这是您代码中的瓶颈,并且您已经验证不必太担心效率,因为这里的逻辑是合理的。您可以避免创建临时数组列表,而是直接创建您知道所需大小的数组。

        【讨论】:

        • 我不知道这是否会成为瓶颈。但我也有兴趣学习其他改进方法
        【解决方案5】:

        如果您想将域和端口保持在一起,那么我相信您将需要两个拆分。您也许可以使用一些正则表达式魔术来做到这一点,但我怀疑您会从中看到任何真正的性能提升。

        如果你不介意拆分域和端口,那么:

          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);
          }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多