2012-05-16 19 views
7

que tienen la siguiente cadena:
A:B:1111;domain:80;a;b
El A es opcional, así B:1111;domain:80;a;b también es una entrada válida.
El :80 es opcional, así que B:1111;domain;a;b o :1111;domain;a;b son también una entrada válida
Lo que yo quiero es terminar con un String[] que tiene:¿Cuál es una buena manera de dividir cadenas aquí?

s[0] = "A"; 
s[1] = "B"; 
s[2] = "1111"; 
s[3] = "domain:80" 
s[4] = "a" 
s[5] = "b" 

Hice esto de la siguiente manera:

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

Me preguntaba ¿hay una mejor manera de hacer esto? ¿De qué otra manera podría hacer esto de manera más eficiente?

+1

hizo que trató con: s.split ("[;:]") Esta división de expresiones regulares para un char que es ' ; ' o ':' – rascio

+0

¿El dominio siempre será seguido por un '80'? – codaddict

+0

@codaddict: No es opcional también – Jim

Respuesta

2

No hay muchos problemas de eficiencia aquí, todo lo que veo es lineal.

De todos modos, podría usar una expresión regular o un tokenizador manual.

Puede evitar la lista. Usted sabe que la longitud de values y actions, por lo que puede hacer

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; 

Debe ser razonablemente eficiente, a menos que usted insiste en la aplicación de split mismo.

enfoque de bajo nivel no probado (asegúrese de probar la unidad y el punto de referencia antes de su uso):

// 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; 

Nota: este código está optimizado de la manera loca de que considerará un : sólo en el primer componente . Manejar el último componente es un poco complicado, ya que out tendrá el valor -1.

Normalmente usaría no utilice este último enfoque, a menos que el rendimiento y la memoria sean extremadamente importantes. Lo más probable es que todavía haya algunos errores en él, y el código es bastante ilegible, en particular comparado con el anterior.

0

se podía hacer algo como

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

A menos que esto es un cuello de botella en el código y que haya comprobado que no se preocupe tanto de la eficiencia como la lógica aquí es razonable. Puede evitar crear la lista de matriz temporal y, en su lugar, crear directamente la matriz, ya que conoce el tamaño requerido.

+0

No sé si esto es o será un cuello de botella. Pero me gustaría aprender otras formas de mejorar también – Jim

1

Con algunas suposiciones sobre los caracteres aceptables, esta expresión regular proporciona la validación, así como la división en los grupos que desee.

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

Da:

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 

Y

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

Si desea mantener juntos el dominio y el puerto, creo que necesitará dos divisiones. Es posible que puedas hacerlo con algo de magia regex, pero dudo que veas un rendimiento real en ella.

Si no le importa dividir el dominio y el puerto, entonces:

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