List.contains(object)
Jonas Abreu em 25/03/2012Em uma consultoria, no segundo dia de trabalho, subi o profiler para ter uma idéia geral de onde estava sendo gasto processamento na carga de uma página que demorava alguns segundos para carregar.
Assim que tudo estava pronto, acessei a página e vi o contador do método equals
de uma entidade disparar
para a lua. Basicamente para cada acesso, o equals
da entidade era chamado 4 milhões de vezes.
Isso obviamente chamou a atenção e passei a procurar a razão disso.
A aplicação possuía uma cache contendo cerca de 1,5 milhões dessas entidades para não precisar ir ao
banco a cada requisição. O problema é que essas entidades estavam armazenadas em um java.util.List
.
A List
é uma estrutura de dados muito boa para acesso posicional (se a implementação usar um array -
java.util.ArrayList
- para manter os dados), mas é péssima para fazer busca por dados, porque precisa
checar um por um os elementos, o que faz no método List.indexOf
. O List.contains
delega a chamada
para o List.indexOf
. E esse era o problema.
Uma simples mudança de estrutura de dados (troquei para um java.util.concurrent.ConcurrentHashMap
) fez com
que o tempo de carga da página caísse 60%.
Basicamente, só use o List.contains
em listas em que você tem certeza que o tamanho é pequeno (no máximo
algumas centenas) e são feitas poucas chamadas a esse método. De resto, troque a estrutura de dados.