Eu que nao tava me lembrando do StringTokenizer… :oops:
Resolvi assim:
private static String getNivelComTokenizer(String str, int nroNivel){
StringTokenizer t = new StringTokenizer(str, ".");
String ret = "";
int i = 0;
while(t.hasMoreElements()){
ret += t.nextElement();
i++;
if(i == nroNivel){
break;
}
//Preciso adicionar o .
ret += ".";
}
return ret;
}
Só mais uma coisa: eu usaria StringBuilder para as variáveis ret, pois melhora ainda mais o desempenho. Apesar de o Tokenizer se sair um pouco mais rápido em algumas vezes, como já dito ele já é um “idoso” e eu considero mais legível o código com o split. Mais aí vai de cada um.
De fato, também fiz uns testes e o StringTokenizer é mais rápido. Mas a diferença só é significativa para enormes quantidades. A média de diferença é de 0,1 milissegundo por iteração. A adaptação para o StringBuilder ficaria assim:
// feito com Tokenizer
public static String getNivelTokenizer(String s, int nivel) {
StringTokenizer token = new StringTokenizer(s, ".");
StringBuilder result = new StringBuilder();
int i = 0;
while (token.hasMoreElements()) {
result.append(token.nextToken());
if (++i == nivel) {
break;
}
result.append(".");
}
return result.toString();
}
// feito com o split
public static String getNivelSplit(String s, int nivel) {
String[] niveis = s.split("\.");
StringBuilder result = new StringBuilder();
int i = 0;
for (String a : niveis) {
result.append(a);
if (++i == nivel) {
break;
}
result.append(".");
}
return result.toString();
}
Realmente StringTokenizer é mais rápida que loucura, alguém me explica como uma classe antiga pode ser mais rápida:
package br.com.pedrosa.teste;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class Teste {
public static void main(String[] sss) throws Exception {
List<String> a = new ArrayList<String>();
Teste teste = new Teste();
for (int i = 0; i < 1000; i++) { // Inicializo o ArrayList
a.add("1.2.3.4.5.6.7.8.9"); // com 9 niveis
}
for (int nroNivel = 1; nroNivel < 10; nroNivel++) {
long tempoInicial = System.currentTimeMillis();
for (int i = 0; i < a.size(); i++) {
teste.getNivelTokenizer(a.get(i), nroNivel);
}
System.out.printf("Resultado Final StringTokenizer %.3f ms%n", (System.currentTimeMillis() - tempoInicial)/ 1000d);
for (int i = 0; i < a.size(); i++) {
teste.getNivelSplit(a.get(i), nroNivel);
}
System.out.printf("Resultado Final Split %.3f ms%n", (System.currentTimeMillis() - tempoInicial)/ 1000d);
}
}
public String getNivelTokenizer(String s, int nivel) {
StringTokenizer token = new StringTokenizer(s, ".");
StringBuilder result = new StringBuilder();
int i = 0;
while (token.hasMoreElements()) {
result.append(token.nextToken());
if (++i == nivel) {
break;
}
result.append(".");
}
return result.toString();
}
// feito com o split
public String getNivelSplit(String s, int nivel) {
String[] niveis = s.split("\.");
StringBuilder result = new StringBuilder();
int i = 0;
for (String a : niveis) {
result.append(a);
if (++i == nivel) {
break;
}
result.append(".");
}
return result.toString();
}
}
Mas cuidado ao concatenar String evite o += sempre use StringBuilder com append.
Por que é mais rápida eu não sei, mas a documentação é bem clara quanto ao seu uso:
Ou seja, ainda existe apenas para compatibilidade com programas antigos. Não use em códigos novos! Use o split da classe String ou o pacote java.util.regex.