Performance de Strings

Fala aew galera,

qual dos tipos de string é a melhor para quem visa velocidade.
String, StringBuilder e assim por diante.

Para melhor vizualização um código simples para ter em mente a performance,
imaginando que sejam 1 milhão de registros.

<T> string = “” [ou new <T>()];
while(ResultSet.Next()){

string += ResultSet.toString();

}

Acredito que seja o StringBuffer.
Ex.:
StringBuffer sb = new StringBuffer();

while(ResultSet.Next()){
sb.add(ResultSet.toString());
}

Nenhum deles. Eles não vão aguentar a concatenação de 1 milhão de registros.

O que tem melhor performance é o StringBuilder que so está disponivel a partir do Java 5, o StringBuffer é sincronizado, e cuidado com essa query de 1 milhão de registros tente colocar filtros, independente que voce ta fazendo ninguem precisa de 1 milhão de registros de uma vez, nem o google traz todos seus resultados de uma so vez.

Bruno era só uma ilustração…

O que realemnte eu quero saber é o tipo de string mais adquado para velocidade de processamento o mais alto possível…

:hunf:

De qualquer forma obrigado… :roll:

Algumas informações:
String: sequência de caracteres imutável. A cada operação de alteração, um novo objeto será criado. Mais rápida para manipulação de texto fixo.
StringBuffer: Cria strings à partir de métodos sincronizados, o que é bom para multithread, mas ruim para a performance singlethread.
StringBuilder: semelhante ao StringBuffer, porém sem sincronização, teoricamente mais rápido em singlethread.

Fica a seu critério qual será mais adequada.

Na verdade nenhuma. Quando o código é gerado e ele “prevê” que vá ter muitas concatenações, ele muda o tipo do objeto para StringBuilder e faz as concatenações um pouco mais inteligentes ( sem gerar novos objetos a toa ). Faça um teste: faça uma classe com String e um for com concatenações e compile-a. Depois rode

javap -verbose SuaClasse e veja qual é o bytecode gerado.

Até!

O toString é mais lento que (String).

2 cents.

[quote=aleck]O toString é mais lento que (String).

2 cents.[/quote]
Baseado em que? Mesmo String chama o método toString(implicitamente) quando precisa pegar o seu conteúdo.

Até!

[quote=maquiavelbona][quote=aleck]O toString é mais lento que (String).

2 cents.[/quote]
Baseado em que? Mesmo String chama o método toString(implicitamente) quando precisa pegar o seu conteúdo.

Até![/quote]

O cast é apenas para verificar o tipo em tempo de compilação, o toString precisa verificar se o metodo realmente retorna uma String.

[quote=aleck][quote=maquiavelbona][quote=aleck]O toString é mais lento que (String).

2 cents.[/quote]
Baseado em que? Mesmo String chama o método toString(implicitamente) quando precisa pegar o seu conteúdo.

Até![/quote]

O cast é apenas para verificar o tipo em tempo de compilação, o toString precisa verificar se o metodo realmente retorna uma String.

[/quote]
Ah tá, não entendi como casting. Mas mesmo o casting exige que a classe possa ser receber tal casting e o método toString implementado garante que o conteúdo que você receberá será um objeto do tipo String ( o valor pode não ser definido mas não vai ser o cast que vai pegar o valor do objeto e devolver como String). Se você der um cast em um Integer para um String ele vai dar erro. Casting tem um uso específico e o método toString outro.

Até!

Concordo, mas me referia mesmo em relação a performance.

Segue um exemplo para comprovar:


import java.util.HashMap;

public class Test {

	public static void main(String[] args) {

		Test performanceTest = new Test();
		performanceTest.zillion();

	}

	void zillion() {
		HashMap map = new HashMap();
		map.put("1", "1");
		map.put("2", "2");
		map.put("3", "3");
		String key = "2";
		final int LOOPS = 10000000;
		//
		long time = System.currentTimeMillis();
		for (int i = 0; i < LOOPS; i++) {
			String item = (String) map.get(key);
		}
		System.out.println("Cast= " + (System.currentTimeMillis() - time));
		//
		time = System.currentTimeMillis();
		for (int i = 0; i < LOOPS; i++) {
			String item = map.get(key).toString();
		}
		System.out.println("toString= " + (System.currentTimeMillis() - time));
	}

}

Pelos seu conceito os meus testes deveriam ser o contrário:

[zillertal:~]$ java Test Cast= 91 toString= 96 [zillertal:~]$ java Test Cast= 98 toString= 87 [zillertal:~]$ java Test Cast= 92 toString= 97 [zillertal:~]$ java Test Cast= 96 toString= 87 [zillertal:~]$ java Test Cast= 92 toString= 96 [zillertal:~]$ java Test Cast= 102 toString= 88 [zillertal:~]$ java Test Cast= 99 toString= 88 [zillertal:~]$ java Test Cast= 96 toString= 86 [zillertal:~]$ java Test Cast= 97 toString= 87 [zillertal:~]$ java Test Cast= 87 toString= 87 [zillertal:~]$

Ou seja: micro-testes não provam nada. Melhor seria ter as operações feitas por cada trecho de código esperado. Mas nós podemos ver o que acontece pelos bytecodes usando o javap. Segue um trecho ( o javap completo está em anexo ):

/* Do primeiro for */ 43: iconst_0 44: istore 6 46: iload 6 48: ldc #12; //int 10000000 50: if_icmpge 69 53: aload_1 54: aload_2 55: invokevirtual #13; //Method java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object; 58: checkcast #14; //class java/lang/String 61: astore 7 63: iinc 6, 1 66: goto 46

/* Do segundo for*/ 104: iconst_0 105: istore 6 107: iload 6 109: ldc #12; //int 10000000 111: if_icmpge 130 114: aload_1 115: aload_2 116: invokevirtual #13; //Method java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object; 119: invokevirtual #23; //Method java/lang/Object.toString:()Ljava/lang/String; 122: astore 7 124: iinc 6, 1 127: goto 107

Ou seja: eles fazem o mesmo número de operações, o toString não tem que verificar o tipo pois ele pega o método herdado de java.lang.Object ( que por coincidência o objeto no Map é do tipo String ). Então é razoávelmente sem fundamento falar que um é mais rápido do que outro sem provas mais concretas.

Até!

Sobre se o método retorna uma String ou não, quem cuida disso é a compilação e não a execução. Não há gasto de tempo nesse trecho ( pois senão nem compilaria ).

Até!