2012-05-16 4 views
7

У меня есть следующая строка:
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(); 

Мне было интересно, есть ли лучший способ сделать это? Как еще я могу сделать это более эффективно?

+1

Возможно, вы пытались с: ДЕЛЕНИЕ («[;:]») Это регулярное выражение раскола для полукокса, который является " ;» или ':' – rascio

+0

За доменом всегда будет следовать '80'? – codaddict

+0

@codaddict: Нет, это необязательно. – Jim

ответ

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.

Я бы, как правило, не использовал этот последний подход, если только производительность и память не имеют решающего значения. Скорее всего, в нем все еще есть некоторые ошибки, и код довольно нечитабельный, особенно в сравнении с приведенным выше.

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

Если это не является узким местом в вашем коде и вы проверили, что не сильно беспокоиться об эффективности, поскольку логика является разумным. Вы можете избежать создания списка временных массивов и вместо этого создать массив так, как вам известно, необходимого размера.

+0

Я не знаю, является ли это или будет узким местом. Но мне было бы интересно изучить другие способы улучшения – Jim

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 
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); 
    } 
Смежные вопросы