Qual collection usar neste caso (java 4)

Boa tarde a todos,

Gostaria de pedir a ajuda de vocês para uma escolha aqui:

O meu cenário é o seguinte: Tenho uma aplicação rodando sobre java 1.4, sendo que esta aplicação possui uma coleção que eu quero usar como uma fila sem repetições, nessa coleção eu insiro itens no final, antes de inserir o item eu chamo o método contains para verificar se o item a ser inserido ja existe na fila (é uma “fifa” como eu costumo chamar, do inglês first in first out, que é uma fila mesmo). Enquanto em uma Thread eu estou obtendo o primeiro item processando e em seguida removendo, em outras várias threads eu insiro itens no final da fila.

Os itens desta fila são VOs, nos quais eu gerei direto no eclipse o equals e o hash code usando apenas um int que representa um identificador único na base de dados, creio que é um equals rápido e funcional ja que esse identificador não se repete.

Isso se encaixaria perfeitamente no que temos o LinkedList como uma Queue, porém Queue não existe no java 1.4, então não tenho os métodos pool e peek de Queue em LinkedList, não sei se deveria usa-lo, então na incerteza estou usando ArrayList mesmo.

Não estou usando um Set por que para obter os itens teria que itera-los, assim ao adicionar um item em uma thread, a próxima iteração geraria uma cocurrentModificationException, não estou usando um map por que para obter os itens teria que iterar as chaves tendo assim o mesmo problema, java 4 não tem queue, só me sobrou list (correto né?).

Estou usando um ArrayList como fila, obtendo e removendo o primeiro item da lista, inserindo sempre no final, porém ao inserir, eu verifico se o item em questão ja existe, como disse, pelo contains da lista, que usa o equals que citei (comparando por um int apenas), e é ai que está o meu problema, essa verificação está lenta em produção quando a lista fica muito grande (em horários de pico de transações). Essa verificação é necessária pro que List permite repetições e eu não quero, um Set não aceitaria mas pelo que eu sei não da para eu usar um set como citei.

Alguém tem alguma sugestão para manter isso funcionando e de forma mais performatica? alguma sugestão?

Cara teria que usar uma lista sincronizada, como um vector por exemplo! O set ele resolveria o seu problema de ser único, porém, não manteria a ordem! Vou dar uma olhada na api de collections para ver se tem alguma que atenda os seus requisitos!

eu posso estar enganado, mas acredito que um vector manteria o problema do list de permitir duplicatas e ainda por cima seria mais lento que o list… mas aceito mais sugestões…

[quote=wellington.nogueira]Minha opinião, implemente sua própria Queue.
Internamente, ao invés de usar o contains de list, use um Set como referência. Faça um add nele e verifique o retorno. Se for true, vc pode adicionar na list. Se for false não adicione pois o mesmo já existe.

Ao remover, remova de ambas as coleções.

[EDIT]
Mantenha o primeiro registro num atributo para um acesso mais rápido e troque-o sempre que chamar o método poll e retorne o mesmo pelo peek.

[EDIT 2]
O quão grande fica essa tua lista? Será que o problema de performance não seja outro? Como pouco espaço de memória para a jvm?[/quote]

quanto a criar minha própria Queue com um Set e o List dentro, acho que é o ideal mesmo, para agilizar o contains, que é o que não esta satisfazendo muito bem…

quanto ao primeiro edit gostei principalmente pelo reaproveitamento, caso va usar isso depois, não se enicaixa nesse caso onde do apenas um peek e após isso um remove, mas pode ser util no futuro.

quanto ao segundo edit, em produção eu acabei por não logar o tamanho da lista, acredito que seja isso por que deu problema em produção onde este módulo parou de processar, não tive log de erros (o que me faz desconfiar de algo não tratado como uma OutOfMemory por exemplo, em todo caso caso adicionei um catch para Throable em alguns lugares onde tinha me esquecido de fazer isso), fiz uns testes com o list contendo 5000 destes VOs ± e o contains ficou lento, acredito ser alguma coisa do tipo… exceto pelo contains, o resto manteve rápido, vo fazer o esquema do Set para testar a performance disso.

Como disse, acho que você tem razão, pode ser problema de memória sim, não só por essa parte da aplicação que não me parece ser pesada, mas sim por que essa aplicação é bem grandinha, não vai sobrar muita memoria mesmo… vou analisar a diferença usando mais memória nos parâmetros de inicialização da aplicação.

Muito obrigado pelas suas considerações, acredito que serão uteis.

Minha opinião, implemente sua própria Queue.
Internamente, ao invés de usar o contains de list, use um Set como referência. Faça um add nele e verifique o retorno. Se for true, vc pode adicionar na list. Se for false não adicione pois o mesmo já existe.

Ao remover, remova de ambas as coleções.

[EDIT]
Mantenha o primeiro registro num atributo para um acesso mais rápido e troque-o sempre que chamar o método poll e retorne o mesmo pelo peek.

[EDIT 2]
O quão grande fica essa tua lista? Será que o problema de performance não seja outro? Como pouco espaço de memória para a jvm?