Ola pessoal estou a estudar as apostilas da caelum e tou com duvidas neste exercicio que axo que nao fiz da melhor maneira e agradecia que me explicassem melhor se possivel obrigado.
Você quer um algoritmo melhor para imprimir os múltiplos de 3 entre 1 e 100?
Eu usaria módulo.
xandevieira
if(i%3==0){
System.out.println("Numero "+i+" é multiplo de 3 ");}
rodpuc
O código do rdgc é o mais eficiente. Por módulo tb está correto, mas vc faz mais cálculos e ainda tem um if. Não q seja o fim do mundo, mas só p vc entender.
dionat4n
[size=18] Nem tudo é como parecer ser![/size]
Se vocês pretendem deixar o código otimizado ao máximo, devem fazer apenas uma chamada de sistema operacional para imprimir na tela. Para isso precisa armazenar o resultado em memória para depois imprimir apenas uma vez. Utilizar String para isso é inviável em termos de performance, pois ela é imutável. StringBuffer é a classe eficaz para concatenar muitas Strings, pois ela é mutável. StringBuilder faz a mesma coisa, só que previne a concatenação ao objeto de duas ou mais Threads, nesse exemplo não é nececessária pois existe só a Thread padrão que executa o método main().
Eis o código:public static void main(String args[]){
long t1, t2;
t1 = System.currentTimeMillis();
StringBuffer sb = new StringBuffer();
String quebraLinha = "\n";
for (int i = 3; i < 10000; i=i+3){
sb.append(i + quebraLinha);
}
System.out.println(sb.toString());
t2 = System.currentTimeMillis();
System.out.println(t2-t1 + " milisegundos.");
}Para computar e imprimir todos múltiplos de 3 de 1 até 10.000 levou-se 234 milisegundos.
Para aquele código inicial:public static void main(String args[]){
long t1, t2;
t1 = System.currentTimeMillis();
int i;
for (i = 1; i < 100; i++){
i = i + 2;
System.out.println(i);
}
t2 = System.currentTimeMillis();
System.out.println(t2-t1 + " milisegundos.");
}Para computar e imprimir todos múltiplos de 3 de 1 até 10.000 levou-se 953 milisegundos.
Para aquele código incrementando de três em três:public static void main(String args[]){
long t1, t2;
for (int i = 3; i < 10000; i = i + 3) {
System.out.println("Múltiplo de 3: " + i);
}
t2 = System.currentTimeMillis();
System.out.println(t2-t1 + " milisegundos.");
}Para computar e imprimir todos múltiplos de 3 de 1 até 10.000 levou-se 938 milisegundos.
Claro que esses tempos podem variar de acordo com a preempção da Thread que executa o código. Mas pelo que vocês podem ver, imprimir na tela uma vez sequer é muito, muito, muito mais lento do que uma simples otimização de incremento.
maquiavelbona
Sua mensagem está meio certa. Primeiro:
Sim, fazer uma só chamada ao SO torna o seu código mais rápido.
Agora é quase que falácia dizer que concatenar Strings é mais lento que usar StringBuffer/StringBuilder. Quer saber por que? Aprenda a usar o javap.
Até!
dionat4n
maquiavelbona:
Agora é quase que falácia dizer que concatenar Strings é mais lento que usar StringBuffer/StringBuilder.
Se for quase que falácia, então me explique pq esse código com StringBuffer roda em 47ms. long t1, t2;
t1 = System.currentTimeMillis();
StringBuffer s = new StringBuffer();
for (int i = 0; i < 10000; i++) { //47ms
s.append(i + " ");
}
t2 = System.currentTimeMillis();
System.out.println(s);
System.out.println(t2-t1 + "ms.");
E me explique pq esse código abaixo que concatena strings roda em 11422ms. long t1, t2;
t1 = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 10000; i++) { //11422ms
s += i + " ";
}
t2 = System.currentTimeMillis();
System.out.println(s);
System.out.println(t2-t1 + "ms.");
Como se vê, é concatenação em Strings versus concatenação em StringBuilder.
Ainda não enxerguei nenhuma falácia no que eu disse.
diegosantiviago
ViniGodoy
Você trocou as bolas ao explicar do StringBuffer e do StringBuilder nesse caso. O StringBuffer é sincronizado e previne o acesso concorrente, e o StringBuilder, não. Portanto, corrija os seus exemplos para usar o StringBuilder, não o StringBuffer. Veja o que diz a documentação do StringBuffer: “As of release JDK 5, this class has been supplemented with an equivalent class designed for use by a single thread, StringBuilder. The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization.”
Na prática, raramente você utilizará o StringBuffer, pois o acesso concorrente a um único buffer raramente faz sentido. A sincronização só previne que o método append() não seja chamada por duas threads simultâneas, porém, ela não garante nada sobre o que acontece entre duas chamadas ao método append. Por exemplo, se o código strBuf.append("15/09/1980 ").append("log line ");
For executado por duas threads diferentes a saída poderá ser “15/09/1980 log line 15/09/1980 log line” ou poderá ser “15/09/1980 15/09/1980 log line log line”. O que ela não poderá ser (já que o StringBuffer é sincronizado) é "15log/09/li19ne80 15log/09/li19ne80 ".
A solução para isso é sincronizar a classe que contém o StringBuffer, mas nesse caso, a sincronização do buffer em si torna-se desnecessário, e podemos substitui-lo por um stringBuilder.
A concatenação de Strings realmente é mais rápida com essas classes. Ela só não é mais rápida em casos assim:
Mas, realmente, dentro de um while o tempo é incomparavelmente menor, como você mesmo demonstrou.
ViniGodoy
Outra coisa que eu notei…
Já que você está usando o StringBuilder, não use a contatenação dentro do método append, foi feito na linha 7 do programa:
sb.append(i+quebraLinha);
Dessa forma, você pode voltar a incorrer nos custos que queria evitar. No lugar, use o método append do próprio StringBuilder. Uma característica interessante é que esse método retorna o próprio StringBuilder, o que permite-nos chamar em cadeia:
sb.append(i).append(quebraLinha);
Melhor que isso, só se a Sun tivesse escolhido a palavra add no lugar de append…
dionat4n
Você trocou as bolas ao explicar do StringBuffer e do StringBuilder nesse caso. O StringBuffer é sincronizado e previne o acesso concorrente, e o StringBuilder, não. Portanto, corrija os seus exemplos para usar o StringBuilder, não o StringBuffer. Veja o que diz a documentação do StringBuffer: “As of release JDK 5, this class has been supplemented with an equivalent class designed for use by a single thread, StringBuilder. The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization.”
Na prática, raramente você utilizará o StringBuffer, pois o acesso concorrente a um único buffer raramente faz sentido. A sincronização só previne que o método append() não seja chamada por duas threads simultâneas, porém, ela não garante nada sobre o que acontece entre duas chamadas ao método append. Por exemplo, se o código strBuf.append(“1”).append(“2”);
For executado por duas threads diferentes a saída poderá ser 1212 ou poderá ser 1122.
A solução para isso é sincronizar a classe que contém o StringBuffer, mas nesse caso, a sincronização do buffer em si torna-se desnecessário, e podemos substitui-lo por um stringBuilder.
A concatenação de Strings realmente é mais rápida com essas classes. Ela só não é mais rápida em casos assim:
Mas, realmente, dentro de um while o tempo é incomparavelmente menor, como você mesmo demonstrou.
Não troquei as bolas não.
Evitar o acesso concorrente para concatenação no objeto é a mesma coisa que evitar a concatenação ao objeto de duas ou mais Threads ( ao mesmo tempo! esqueci de escrever isso… )
dionat4n
ViniGodoy:
Outra coisa que eu notei…
Já que você está usando o StringBuilder, não use a contatenação dentro do método append, foi feito na linha 7 do programa:
sb.append(i+quebraLinha);
Dessa forma, você pode voltar a incorrer nos custos que queria evitar. No lugar, use o método append do próprio StringBuilder. Uma característica interessante é que esse método retorna o próprio StringBuilder, o que permite-nos chamar em cadeia:
sb.append(i).append(quebraLinha);
Melhor que isso, só se a Sun tivesse escolhido a palavra add no lugar de append…
Com certeza, eu até iria fazer isso, mas daí ficaria diferente do programa anterior, pois eu queria adicionar strings propriamente dito.
ViniGodoy
Ué, se não trocou as bolas, porque seu código está com o StringBuffer, e não o StringBuilder, quando a documentação diz que é justamente o contrário que se deve fazer?
Sua explicação está trocada sim cara. Leia o Javadoc.
dionat4n
ViniGodoy:
Ué, se não trocou as bolas, porque seu código está com o StringBuffer, e não o StringBuilder, quando a documentação diz que é justamente o contrário que se deve fazer?
Sua explicação está trocada sim cara. Leia o Javadoc.
Viajei total! hauehuaehuea
É verdade, troquei as bolas…
Se bem que quem nomeou essas classes poderia colocar algo mais sugestivo…
Valeu!
maquiavelbona
dionat4n:
…
Ainda não enxerguei nenhuma falácia no que eu disse.
Agora vamos com as considerações:
-testes de microscópio nada inferem. Sua máquina poderia estar rodando algo em algum momento;
-você viu em algum lugar que o código concatena Strings diretamente? Ou será que o compilador foi esperto o suficiente para saber que tinha um loop concatenando String?
Até!
dionat4n
Eu executei diversas vezes o mesmo código para me certificar disso. Se duvida, faça isso.
Nesse link abaixo esclarece tudo:
“In conclusion, StringBuffer concatenation is significantly faster than String concatenation. Obviously, StringBuffers should be used in this type of operation when possible. If the functionality of the String class is desired, consider using a StringBuffer for concatenation and then performing one conversion to String.” http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html
Obrigado pela insistência, na próxima terei que analisar melhor isso.
B
Bruno_Laturner
dionat4n:
Eu executei diversas vezes o mesmo código para me certificar disso. Se duvida, faça isso.
Nesse link abaixo esclarece tudo:
“In conclusion, StringBuffer concatenation is significantly faster than String concatenation. Obviously, StringBuffers should be used in this type of operation when possible. If the functionality of the String class is desired, consider using a StringBuffer for concatenation and then performing one conversion to String.” http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html
Em 2000 isso era verdade.
Hoje em 2009, muita coisa foi otimizada no Java 6, concatenação de Strings é uma delas. Não há mais tanta diferença.
dionat4n
Bruno Laturner:
dionat4n:
Eu executei diversas vezes o mesmo código para me certificar disso. Se duvida, faça isso.
Nesse link abaixo esclarece tudo:
“In conclusion, StringBuffer concatenation is significantly faster than String concatenation. Obviously, StringBuffers should be used in this type of operation when possible. If the functionality of the String class is desired, consider using a StringBuffer for concatenation and then performing one conversion to String.” http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html
Em 2000 isso era verdade.
Hoje em 2009, muita coisa foi otimizada no Java 6, concatenação de Strings é uma delas. Não há mais tanta diferença.
Tem razão… Mas o que rodei aqui foi no Java 6, estranho.
Por favor, não ressuscite tópicos antigos para repetir o que já foi dito.
Sua solução já está nesse mesmo tópico, aqui:
Se for ressuscitar tópicos, deixe claro que está fazendo isso, e faça apenas se tiver uma solução inédita e mais eficiente para o problema.
Evite simplesmente responder a dúvida como se ela fosse postada ontem, pois isso confunde outros respondentes.