Mensagens enviadas por: saoj
Índice dos Fóruns » Perfil de saoj » Mensagens enviadas por saoj
Autor Mensagem
Perde tempo respondendo a esse tópico inútil... (oops)

Ok, perde tempo escrevendo algo mais elaborado aqui...
nel wrote:Entendo.

Basicamente, as tecnologias WEB permitem que eu trabalhe diretamente com o objeto retornado pelo lado servidor. Há poucas situações em que uso o índice para remover apenas da lista, get(i), pois 90% (senão mais) envio diretamente o objeto ao lado servidor, ao menos, o seu respectivo ID. Normalmente, essas listas representam dados populados diretamente no banco, portanto, removeu da lista, remove-se do banco e não trabalha com o remove(i).

A dúvida foi ali pois se encaixava ainda nos 10%. De qualquer forma, vou começar a reavaliar o código que ainda usa o índice e se realmente é necessário.
Grato por todas as opiniões e esclarecimentos.


O que vc pode fazer é:

Ao invés de ter um ArrayList por índice, vc pode ter um LinkedHashMap por *id do banco*. Acho que dá no mesmo mas fica mais organizado e com uma performance melhor. Claro que essa diferenca de performance vai ser totalmente irrelevante para a sua aplicacao, mas acho que fica mais consistente usar id do banco em tudo. Mas isso é um chute sem conhecer muito bem o seu caso específico.

Remove diretamente de listas, realmente não posso opinar muito porque não uso. E não vejo necessidade.


Boa resposta. Concordo com o que vc falou sobre usar a chave primária do objeto ao invés do índice na lista.

Sobre a necessidade de remover, me recomendaram o LinkedHashSet ou o LinkedHashMultiset do Guava se eu precisar de objetos duplicados na lista.

Excluindo o problema dos objetos duplicados, realmente o que eu queria parece ser um SET ordenado por insercão, ou seja, um SET com uma lista encadeada internamente para manter a ordem. Daí obviamente quando vc remove do set ele vai direto nos ponteiros do elemento e remove ele da lista interna tb. Sem ser louco de loopar...

Tem problemas que são mais simples via recursividade, outros mais simples via loop.

Se a solucão exigir muitas iteracões, vc não pode usar recursividade porque o stack é limitado.

Entenda bem os dois! Os problemas mais casca-grossa são mais fáceis de resolver via recursividade. Tentar resolve-los vai for é muito mais difícil. Não vale a pena nem comecar...

Acho que o problema aí é que mesmo que eu já tenha o objeto a ser removido, eu não tenho como removê-lo sem percorrer a lista inteira atrás dele. Concorda? Seja via remove(indice) ou via remove(object).

E numa linked list, que na verdade é uma double-linked list, tendo algum node da lista fica muito fácil remove-lo. Basta atualizar os ponteiros (node.prev and node.next). Mas no java.util.LinkedList, eu não tenho acesso ao objeto Node, logo tenho que loopar atrás dele.


Mas , por exemplo, quando vc lê de um ResultSet JDBC quando usar ? LinkedList ( porque mesmo o tamanho sendo fixo, vc não sabe qual é).


Foi o que eu falei inicialmente: se vc não sabe quantos elementos vc vai ter que colocar na sua lista, só dá pra ir de LinkedList. Agora se vc sabe de antimão o tamanho (máximo) da sua lista (veja que tamanho != capacidade), então vc pode ir de ArrayList sem problemas. O que o cara pode fazer é pegar um tamanho máximo bem grande para nunca estourar o ArrayList, mas ir de LinkedList nesses casos me parece mais correto, a não ser que vc realmente precisa de indexação no resultado retornado. Quando vc precisa de indexação, só se pode ir de ArrayList.

Então repetindo a minha frase inicial: "Como regra eu só uso ArrayList quando preciso de INDEXAÇÃO ( list.get(3) ) ou QUANDO O TAMANHO DA MINHA LISTA É CONHECIDO NA HORA DA CRIAÇÃO."

Agora se vc precisa de REMOÇÃO de qualquer objeto aleatório da lista (não é o caso de quando vc está iterando), então nem o ArrayList e nem o LinkedList vão prestar. Eu implemento minha própria linked list e faço meus objetos extenderem Node (nao ideal mas funciona que é uma beleza). Fiquei agora curioso para saber qual é a solução padrão que o Java oferece nesse caso, ou seja, qual é a solucao padrão que o Java oferece para linked lists onde eu possa remover qualquer elemento de forma rápida via um list.remove(elemento).
ViniGodoy wrote:A remoção durante a iteração também costuma a ser mais rápida no LinkedList.


Nesse caso aqui eu diria muito melhor porque vc nunca paga o preco do SHIFT do ArrayList. Era o meu ponto. Remocao numa LinkedList é mais rápida do que numa ArrayList.

O problema não é a remocao em si, mas ter que encontrar o objeto a ser removido dentro da lista, linearmente, via iteracao.

O fato de eu usar minha própria linkedlist onde os objetos que eu coloco dentro dela SÃO um entry dessa lista, me livra desse problema. Só que para uma java.util.LinkedList que precisa aceitar objetos quaisquer, não há como escapar desse custo de encontrá-los quand se quer removê-los. A não ser que como vc mencionou muito bem, vc já tenha que iterar sobre eles de qualquer jeito...

Acho que eu é que estava errado aqui.

O problema é simples. Apesar de em teoria remocao numa linked list ser sempre mais rápida que remocão num array, o problema está no fato de que o java.util.LinkedList não lhe dá acesso ao objeto LinkedList.Entry, ou seja, de posse do objeto a ser removido, vc não tem como fazer essa remocão no LinkedList sem antes pagar o preco de encontrá-lo, *mesmo que vc já o tenha*.

Então por causa disso o outro Sergio falou que remocao no LinkedList é custoso. Não é a remocao em si, mas sim o preco que vc precisa pagar para encontrar o objeto a ser removido.

O que vai acontecer é que o LinkedList vai ser mais rápido se o objeto a ser removido estiver no início da lista e o ArrayList vai ser mais rápido se o objeto a ser removido estiver no final da lista. (Assumindo uma lista relativamente grande)

O ideal é vc ter a sua própria implementacão de LinkedList onde o objeto que vc coloca na sua lista extende ou implementa um Entry dessa lista. Daí de posse do objeto vc pode rapidamente remove-lo sem qualquer custo de encontrá-lo. Mas como vc encontrou o objeto primeiro de tudo? Provavelmente veio de um map...
saoj wrote:

Detalhe, linked é mais rápido para inserção e remoção nas extremidades da lista ( por isso tem métodos como removeFirst() e removeLast() ) , mas é mais lento para remoção de um elemento no interior.


Acredito que essa afirmacão está errada. Quando vc remove um elemento do interior de uma lista, ArrayList vai requerer um SHIFT bastante custoso. Já no LinkedList essa operacao é bem rápida. É o oposto do que vc afirmou aí em cima.



Acho que eu entendi agora a confusão. O problema não é a REMOCÃO em si. O problema é a LOCALIZACÃO do elemento no meio da linked list. Obviamente vc não vai poder usar indexacão. Mas quando se diz que REMOCAO numa LinkedList é mais rápida que uma REMOCAO num ArrayList, é claro que se está assumindo que o elemento a ser removido já está em mãos, daí basta fazer a atualizacao na sua double linked list.

Acho que se vc está falando de uma java.util.LinkedList, vc terá que sempre pagar o preco de encontrar o elemento a ser removido, então isso será um problema, não pela remocao em si, mas por ter que achar o elemento na lista.

Note que se estiver removendo elementos próximos do início, o custo de achá-los será baixo enquanto a remocao será bem rápida. Sendo a lista longa, teríamos um custo bastante alto de shift caso estivéssemos utilizando um ArrayList. O que vai acontecer é que o LinkedList vai ser mais rápido se o objeto a ser removido estiver no início da lista e o ArrayList vai ser mais rápido se o objeto a ser removido estiver no final da lista. (Assumindo uma lista relativamente grande)

O ideal é vc ter a sua própria implementacão de LinkedList onde o objeto que vc coloca na sua lista extende ou implementa um Entry dessa lista. Daí de posse do objeto vc pode rapidamente remove-lo sem qualquer custo de encontrá-lo. Mas como vc encontrou o objeto primeiro de tudo? Provavelmente veio de um map, estava cacheado em algum lugar, não-interessa... De posse desse objeto eu não deveria ter que encontrá-lo novamente na lista para remove-lo, sendo essa lista uma (double) linked list.

Sendo a java.util.LinkedList uma lista de objetos genéricos, vc sempre cai no problema de ter que encontrá-los na lista. Por essa lado o errado aqui sou eu.
nel wrote:
saoj wrote:
nel wrote:
O LinkedList só é muito bom para remover o primeiro e último item da lista, não os seus "interiores", porque tem métodos como o removeLast()


Na boa, não sei de tudo e estou sempre aprendendo, mas nesse caso acima vc está falando uma besteira sem tamanho. Vc sabe o que é shift? Acho que não...



Leu o link que passei ?


Li e coloquei a minha observacao lá. Vc confiou cegamente no meu chará. Recomendo não acreditar em ninguém, nem em mim. Faca vc mesmo suas pesquisas e tire vc mesmo suas conclusões. Qualquer um pode falar besteira.

Errar é humano. Insistir no erro sem aprender e sem fazer suas proprias pesquisas é que é o problema.

Detalhe, linked é mais rápido para inserção e remoção nas extremidades da lista ( por isso tem métodos como removeFirst() e removeLast() ) , mas é mais lento para remoção de um elemento no interior.


Acredito que essa afirmacão está errada. Quando vc remove um elemento do interior de uma lista, ArrayList vai requerer um SHIFT bastante custoso. Já no LinkedList essa operacao é bem rápida. É o oposto do que vc afirmou aí em cima.

nel wrote:
O LinkedList só é muito bom para remover o primeiro e último item da lista, não os seus "interiores", porque tem métodos como o removeLast()


Na boa, não sei de tudo e estou sempre aprendendo, mas nesse caso acima vc está falando uma besteira sem tamanho. Vc sabe o que é shift? Acho que não...

nel wrote:
saoj wrote:Da onde vc tirou que o cara tem que usar LinkedList quando houver indexacao?


Ué, foi você mesmo que disse isso, eu não falei isso. A indexação que você se refere foi um get(3). Se for um get(900000) ?


Tá bem claro na primeira linha do meu post que INDEXACÃO => ArrayList, nunca LinkedList. Eu não sei da onde vc tirou essa idéia de que eu falei que LinkedList é bom para indexacão. Isso é o básico do básico.

nel wrote:
Sempre é uma palavra forte, eu diria em 99% das coisas que ela é incluída. Se é sempre, você está me dizendo que usar uma LinkedList para manipular listas que ultrapassam a casa dos 100 mil objetos, é tranquilo, é isso ? Você pode remover qualquer posição colega, não necessariamente a última. Discordo plenamente da sua afirmação que LinkedList é melhor para remoção de objetos.


Acho que vc deveria rever os seus conceitos sobre remocao. LinkedList NUNCA requer shift na hora remover. ArrayList SEMPRE requer, com excecão do caso especial quando vc está removendo o último elemento. Conclusão: LinkedList é preferível para remocões. Não sei da onde vc tirou que ArrayList é melhor para remocão. E isso não muda tendo a sua lista 10 ou 10 milhões de objetos.

nel wrote:
Ninguém quer redimensionar um Array, todavia, 99% das ações que tomo não tenho conhecimento do tamanho de array que estarei manipulando. Quando eu sei, a história é outra.


Então vai de LinkedList se não precisar de indexacão. Geralmente é esse o caso quando vc não sabe o tamanho da sua lista, ou seja, vc não vai precisar de indexacao e vai usar iterators.

Repetindo o meu IF/THEN/ELSE que acredito trata a grande maioria dos casos:

Como regra eu só uso ArrayList quando preciso de INDEXAÇÃO ( list.get(3) ) ou QUANDO O TAMANHO DA MINHA LISTA É CONHECIDO NA HORA DA CRIAÇÃO.

if (precisa de indexacao OR a lista possui um número de elementos fixo que vc conhece de antimão) then ArrayList else LinkedList.

Acho que vc não entendeu o IF/THEN/ELSE.

nel wrote:
Por se tratar de uma lista encadeada, fica necessário que ela percorra item á item, até chegar ao item escolhido


Claro. E foi por isso que eu disse:

saoj wrote:
Como regra eu só uso ArrayList quando preciso de INDEXAÇÃO


Da onde vc tirou que o cara tem que usar LinkedList quando houver indexacao?

nel wrote:
Se houver necessidade de manipulação na lista, como remoções, um LinkedList pode vir a lhe dar dor de cabeça e nesse caso eu aconselho ArrayList.


Vc está errado aqui. Remocão é sempre melhor com LinkedList pois não requer shift, a não ser que vc esteja removendo o último elemento. Da onde vc tirou que é melhor usar ArrayList?

nel wrote:
A questão de conhecer o tamanho da lista, acho desnecessário. Por default, um ArrayList é criado com 10 posições.


Vc não entendeu. A última coisa que vc quer é ter que redimensionar um ArrayList. Quando vc tem certeza do tamanho do array, esse problema desaparece.

nel wrote:
Mas a API Collection é bem ampla e dispõe de inúmeros implementações, portanto, um bom estudo sobre ela é ideal para saber escolher a API mais adequada para a sua necessidade.



Como regra eu só uso ArrayList quando preciso de INDEXAÇÃO ( list.get(3) ) ou QUANDO O TAMANHO DA MINHA LISTA É CONHECIDO NA HORA DA CRIAÇÃO.

Acho que tirando esses dois casos aí em cima eu quase sempre vou de LinkedList.

Alguém discorda? Posso estar esquecendo algum outro caso, mas esses são o que vem a minha cabeça de forma automática e acredito ser a regra básica que todos deveriam utilizar.


Tive que olhar no dicionário o que é discorrer: http://www.dicionarioinformal.com.br/discorrer/



Esse tópico fala tudo sobre isso: http://www.guj.com.br/java/252013-voce-nao-gosta-do-hibernate-eu-tb-nao-leia-para-entender-o-porque

Simplificando: se vc sabe SQL é preferível utilizar um sql-builder / jdbc-helper com DAO e deixar de fora o hibernate que é uma complexidade maior (hibernate e todas as suas sacanagens, mágicas, suposições, HQL, Criteria, annotations, etc.) para simplificar uma complexidade menor (jdbc + sql) com ganhos bastante duvidosos.

Na minha humilde opinião abstração só cabe quando há simplificações claras. Hibernate resolve um problema (jdbc + sql) criando outro maior (veja a quantidade de dúvidas no GUJ sobre o Hibernate), logo isso não pode ser chamado de abstração.

Opções: MentaBean (http://mentabean.soliveirajr.com), iBatis, jOOQ, etc.

Eu acredito que essas opcões acima resolvem o problema jdbc de uma forma muito mais simples e menos intrusiva. Agora tem que saber SQL, que é a linguagem nativa dos banco-de-dados. Aprender HQL / Criteria sem saber SQL fica esquisito e com certeza vai te pegar lá na frente.

 
Índice dos Fóruns » Perfil de saoj » Mensagens enviadas por saoj
Ir para:   
Powered by JForum 2.1.8 © JForum Team