在第一次出现数字时分割字符串的最有效方法是什么?

时间:2014-11-20 08:48:04

标签: java arrays regex list char

JamesBond001.txt
JamesBond002.txt
JamesBond003.txt

我想把它分成两部分{JamesBond | 001},{JamesBond | 002},{JamesBond | 003}

4 个答案:

答案 0 :(得分:3)

为了让您做出明智的决定,这里是两个竞争解决方案的基准。

@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
@OperationsPerInvocation(Measure.SIZE)
@Warmup(iterations = 10, time = 100, timeUnit=MILLISECONDS)
@Measurement(iterations = 5, time = 1000, timeUnit=MILLISECONDS)
@State(Scope.Thread)
@Threads(1)
@Fork(1)
public class Measure
{
  public static final int SIZE = 1;

  String toSplit;

  @Setup public void setup() {
    final Random rnd = ThreadLocalRandom.current();
    toSplit = IntStream.range(0, 100)
        .mapToObj(i -> String.valueOf((char)(i < 95? 'A'+rnd.nextInt(20) : '0'+rnd.nextInt(10))))
        .collect(joining());
  }

  static final Pattern regex = Pattern.compile("(?<=\\D)(?=\\d)");

  @Benchmark public String[] regex() {
    return regex.split(toSplit);
  }

  @Benchmark public String[] loop() {
    int i;
    for (i = 0; i < toSplit.length(); i++)
      if (toSplit.charAt(i) >= '0' && toSplit.charAt(i) <= '9')
        break;
    return new String[] { toSplit.substring(0, i), toSplit.substring(i, toSplit.length()) };
  }
}

因此,我们使用100个字符串进行测试,其中最后5个字符是数字。这是关于最糟糕的情况,因为我们必须搜索几乎整个冗长的字符串才能找到分裂点。

结果:

Benchmark            Mode  Samples     Score      Error  Units
o.s.Measure.loop     avgt        5    96,772 ±    8,671  ns/op
o.s.Measure.regex    avgt        5  3720,446 ± 1096,872  ns/op

自定义循环将正则表达式击败到地面,即使我们足够小心地编译正则表达式。

答案 1 :(得分:1)

这是一个紧凑的,可以利用String.indexof的任何特殊效率。我对它的效率感兴趣。

public static int indexAnyOf(String of, String in) {
    for (int i = 0; i < in.length(); i++) {
        if (of.indexOf(in.charAt(i)) != -1) {
            return i;
        }
    }
    return -1;
}

public void test() {
    String agent = "JamesBond007.txt";
    int firstDigit = indexAnyOf("0123456789", agent);
    System.out.println(agent.substring(0, firstDigit) + "|" + agent.substring(firstDigit));
}

答案 2 :(得分:0)

(?<=\D)(?=\d)

试试这个。\n。见。演示。

http://regex101.com/r/lZ5mN8/63

答案 3 :(得分:0)

类似的东西:

    String agent = "JamesBond001.txt";
    int len = agent.length();
    String left = null, right = null;
    for (int i = 0; i < len; i++) {
        if (Character.isDigit(agent.charAt(i))) {
            left = agent.substring(0, i);
            right = agent.substring(i);
            break;
        }
    }

但可能你在错误的地方进行了优化。编写代码,使其清晰,简单并有效,然后测量时间的真正去向。我打赌它并不主要是你应用的这一部分!