7

次の文字列があります。
A:B:1111;domain:80;a;b
これAはオプションであるためB:1111;domain:80;a;b、有効な入力でもあります。もオプションなので
、有効な入力でも あります。 :80B: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();

これを行うためのより良い方法はありますか?他にどうすればこれをより効率的に行うことができますか?

4

5 に答える 5

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

パフォーマンスとメモリが非常に重要でない限り、私は通常、この最後のアプローチを使用しません。おそらくまだいくつかのバグがあり、コードはかなり読めません。特に上記のものと比較してください。

于 2012-05-16T13:08:21.377 に答える
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
于 2012-05-16T13:06:17.710 に答える
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]);
于 2012-05-16T13:03:04.527 に答える
0

これがコードのボトルネックであり、ここでのロジックが妥当であるため、効率についてあまり心配しないことを確認した場合を除きます。一時配列リストの作成を回避し、代わりに、必要なサイズがわかっている場合は配列を直接作成できます。

于 2012-05-16T13:03:14.547 に答える
0

ドメインとポートを一緒に維持したい場合は、2 つの分割が必要になると思います。いくつかの正規表現マジックでそれを行うことができるかもしれませんが、それによって実際のパフォーマンスが向上するかどうかは疑問です.

ドメインとポートを分割しても構わない場合は、次のようにします。

  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);
  }
于 2012-05-16T13:11:18.937 に答える