Collections

6 respostas
L

Ola. Estou criando uns programas e preciso realizar buscas em uma lista que pode conter muitos objetos (muitos quer dizer ateh mesmo algo que consome quase toda a memoria disponivel). Bem, preciso saber se um objeto esta nessa lista antes de adiciona-lo, eu implementei Comparable para o objeto e executei Collections.binarySearch para a lista, porem ela tem que estar previamente ordenada (pelo que entendi no javadoc).
Minhas duvida saum:

  1. existe alguma lista que eu possa inserir ordenado? (procurei no jakarta-commons-collections e tb naum achei). Ou algo que implemente uma arvore de busca balanceada.
  2. Collections.sort, me parece ter um desempenho bom, porem o que eh mais custoso? usar sort a cada adicao de elemento na lista para depois usar binarySearch ou sobrescrever equals para os objetos da lista e testar com contains? acredito que a primeira solucao ainda assim eh melhor mas queria uma opiniao de vcs.
  3. Estou usando ArrayList, soh vi por cima que commons-collection tem um FastArrayList mas ainda naum li a diferenca. Queria saber que lista vcs iriam usar para gerenciar um numero taum grande de objetos com o suporte para fazer consultas.

Eh isso, basicamente o que preciso eh de algum agrupador de objetos (lista, arvore, seila) que possua uma busca extremamente rapida.

ps. A principio (vou dormir agora e soh vou testar de novo amanha anoite), mesmo ordenando a lista depois de adicionar o elemento, ele naum encontrou para alguns elementos no binarySearch. Tem algo a mais que preciso fazer para usar binarySearch? senao eu que devo ter feito algo lusitano aqui (to com sono ja hehe)

bem eh isso ai, valeu, se alguem tiver qq dica ou coisa que possa me ajudar, estamos ai hehe soh para saberem a origem do problema, isso serve para implementacoes de buscas de solucoes para problemas de IA

6 Respostas

L

a próposito, ontem qdo fui durmir, tava pensando, fiz sim ja uma coisa lusitana, minha implementação de compare retorna sempre 0 se for igual ou 1 se for diferente, ao invés de -1 0 1, ai é dificil de se criar uma busca binaria ou ordenação eficiente se um registro é sempre o proximo ou igual.
Porém da forma que esta, provavelmente um sort da vida, iria fazer a ordenacao igual a uma lista ordenada simples, ja que não existe balanceamento, um registro é sempre “maior” que o outro, então teoricamente se fosse representar isso em uma arvore binaria eu teria apenas nós a direita:
No1.dir -> No2
No1-esq -> null
No2.dir -> No3
No2.esq -> null

No(n).dir -> No(n+1)
No(n).esq -> null

Se for assim, não teria motivos para binarySearch não funcionar, pois faria uma busca em uma arvore de um lado soh, e fatalmente passaria por todos registros (até encontrar o que estou procurando), claro que não com a melhor performasse, mas acho que deveria.

Mas tah, isso vai para testes anoite… falei isso só para agregar um pouco mais info ao problema, se alguem tiver sugestões de listas/arvores extremamente rapidas para pesquisas, fala ae. Valeu

C

Irmao, da uma olhada nessa apostila que vai ter um capitulo que fala de collections, ai vai estar a sua resposta. :joia:

L

boa… valeu ae, olhei o TreeSet me parece bem o que eu preciso (vou testar em casa depois), a principio o testezinho que fiz aqui na empresa funcionou e pelo visto o contains dele faz uma busca binaria em um TreeMap, então eh rapido mesmo.

valeu ae cara :wink:

L

pqp, qual o problema do pessoal da sun fazer um metodo

Object get(Object o)

para listas, arvores seila.

Vou explicar porque:
um objeto pode ser “igual”, mas com um detalhe diferente, por exemplo, tenho gravado que chego a Curitiba percorrendo 500km, ai descubro outro caminho percorrendo 300km, em ambos os casos eu estou em Curitiba, mas o segundo caso eh melhor para mim (cidade anterior, para quem conhece o algoritmo de Dijkstra vai entender o que estou falando), entao mais vale eu guardar o segundo caso. Porem se descubro um terceiro caminho percorrendo 900km, entao naum vale, mas para isso preciso obter de novo o de 300 que esta na List. Mas para fazer esse tipo de coisa eu preciso poder buscar o objeto pelo objeto, e naum apenas testar se ele esta inserido (contains)… isso esta me fazendo uma falta tremenda aqui =/

alguem conhece alguma classe que faca isso? meu sonho seria ter um TreeSet com esse metodo, iria me resolver tantos problemas hehe tah certo que Set ja quer dizer unico, mas muitas coisas em IA usam esse conceito de a melhor ou pior, posso ter dois objetos “identicos”, porem um eh melhor que o outro.

Para ajudar a entender a necessidade, exemplo 2 hehe eh como se vcs tivessem uma classe Mulher, uma lista de Mulheres, e vc quer deixar nessa lista as mais bonitas pela cor do cabelo, para vc todas as loiras saum iguais, mas algumas saum mais bonitas, entao equals de Mulher soh testa a cor do cabelo. Ai vc ve uma mulher loira, vc pesquisa na lista se existe uma mulher daquelas, vai te retornar uma ou nenhuma, essa uma que retornou eh a loria mais bonita que vc conhece (porque esta na sua lista), ai vc verifica qual eh mais bonita, se a nova for, vc adiciona a nova encima da antiga :P.
Mas agora pensa que existem milhoes de tipos de cabelos e vc vai analisar milhoes de mulheres, entao algo como

int ix = lista.indexOf(mulher);
if(ix >= 0)
  lista.get(ix);

naum me serve devido a imensa lentidao, eu preciso de algo ordenado com uma busca extremamente rapida. Ai o fato de querer armazenar em uma estrutura de arvore . Mas mesmo se naum fosse para usar arvore, usaria apenas um Set da vida, eu teria que pegar a Mulher que esta no Set e testar ela com a nova, ai que entra o metodo que eu queria, e usar Map naum me serve porque memoria eh algo bem critico e pelo simples fato de eu ter um objeto nem que seja Integer (o HashCode) como key, para algo em torno de milhoes, ja ocupa um bocado.

Desculpa escrever tanto, ou viajens e tal, mas realmente ainda naum achei nada que possa me ajudar.

Eh isso ai, se alguem poder me dar qq dica, qq mesmo eu estou aceitando, eu a principio queria achar uma solucao usando apenas a api padrao da sun, mas se naum tiver (como to achando que naum vai ter), podem me passar frameworks de collections, mesmo que naum me sirva (eu analiso eles e vejo se me serve)… eu soh conheco o da Apache e ateh agora pelo que vi naum me serve tb

valeu!

T

luBs,

gostei do exemplo das mulheres :lol: , mas responda algumas questões…

vc precisa de uma conjunto de objetos ordenados?

vc precisa “sortear” esse conjunto?

os objetos devem ser únicos?

L

Oi Taz, pois eh, exemplos assim ficam mais faceis de entender… bem, o que estou fazendo eh estudano varias coisas de IA, muita coisa ja sei, mas agora resolvi implementar tudo, soh na teoria naum da certo :stuck_out_tongue: … estou tentando fazer um conjunto de classes a principio que fazem buscas de solucoes para problemas de IA, como distancia entre cidade, solucao do jogo dos 8, problema das 8 rainhas, monges e canibais enfim, a pessoa define o estado do problema, o estado solucao e executa uma busca especifica (busca extensao, profundidade, bidirecional, A*, tabu, profundidade iterativa, etc etc etc). A principio eu estou menos preocupado em implementar os varios algoritmos e mais preocupado em melhorar a performasse.

Basicamente meu modelo de testes esta para o jogo dos 8 em uma busca por extensao ou profundidade (o que eh o jogo dos 8: http://www.cos.ufrj.br/~ines/courses/cos740/leila/cos740/apres_ia.pdf). O que um algoritmo de busca faz eh a partir de um estado inicial por exemplo:

1 3 5
2 7 6
8 4 X

gerar estados sucessivos ateh encontrar uma estado objetivo

1 2 3
4 5 6
7 8 X

Por exemplo, fazer uma busca por extensao (bem facinho de implementar, a mais simples) iria colocar o estado inicial em uma fila, e comecaria um looping: enquanto tem itens na Fila OU naum achou estado objetivo, remove da Fila e gera os sucessores do estado, entao a principio estado inicial gera os seguintes sucessores:

1 3 5       1 3 5
2 7 6       2 7 X
8 X 4   e  8 4 6

O estado inicial sai da Fila e os sucessores entram, e assim por diante. Cada sucessor guarda a referencia do seu pai, assim quando chegar a um estado objetivo, eu percorro de volta atraves do seu pai ateh o estado inicial sabendo o caminho da solucao.

Tah, isso que falei naum eh invensao nada, eh um algoritmo de busca bemmm simples… mas como vc pode imaginar, nesse jogo eu posso chegar por diversos caminhos a um estado, e se eu ja analisei e coloquei na fila esse estado, naum eh interessante analisar ele de novo, isso eh uma “otimizacao” para os algoritmos de buscas (chamada de busca em grafo, otimizacao entre “” porque as vezes naum eh interessante usar, em buscas por profundidade por exemplo que a vantagem eh o baixo consumo de memoria, mas depende do problema geralmente). Quando a busca lembra dos estados ja expandidos, eh dito que ela tem uma memoria… e essa memoria que eu quero implementar com Set, pois as buscas ai tem que ser muito rapidas, principalmente nesse tipo de busca por “forca bruta” que geram milhares ou milhoes de estados (dependendo do problema). Bem, mas por exemplo nesse jogo, eu posso chegar de varias formas ao mesmo estado, mas os caminhos para chegar ateh ele podem ser diferentes (ou ateh infinitos caminhos), por exemplo para eu chegar no estado:

1 2 3
4 5 6
7 X 8

eu posso dar uma volta animal ou simplesmente mexer uma peca, entao se eu chegar a um estado ja analisado, aquele estado pode ser o pai de um estado que tem um sucessor que chega ateh a solucao, entao eh bom que eu saiba sempre o menor caminho ateh chegar a qualquer estado do problema, entao naum me interessa apenas saber se ele ja foi analisado (se esta no Set), eu quero saber quantos passos tive que dar para chegar ateh aquele que tenho em memoria, se esse numero de passos for maior que o numero de passos que encontrei agora, eu naum vou espandir ele, mas vou trocar o pai daquele que tenho gravado para ser o pai desse que achei (o algoritmo dijstra - caminho minimo - funciona mais ou menos dessa forma)… tai minha necessidade de conseguir ler um objeto de um set que contem NohDaBusca, e que possui um estado e um pai, posso achar outro NohDaBusca com o mesmo estado (entao eles saum iguais), mas o caminho ateh chegar nele eh diferente, e pode ser melhor que o que tenho gravado.

Bem, pensei em usar um HashMap<HashCode do estado, NohDaBusca>, preciso gravar o noh da busca e naum o int do numero de passos porque nem todos problemas tem melhor solucao pelo numero de passos, as vezes existe custo ou alguma particularidade descrita no problema etc etc. Mas apenas pelo fato de eu ter um integer num hashMap a mais, ja me causa uma perda de memoria consideravel (se expandir 1kk de estados, vou ter 1kk de Integer’s no HashMap a mais)…

Fiz testes aqui com TreeSet, TreeMap, HashMap e HashSet

  • Sobre a memoria, os melhores foram:
    TreeSet -> HashSet -> HashMap -> TreeMap (tah eu naum entendi porque TreeSet consegui inserir mais que em HashSet, ja que TreeSet usa TreeMap, na real nem cheguei a ver muito… mas consegui inserir mais objetos ateh dar OutOfMemory nele no que no HashSet)
  • Sobre a performasse de insercao melhores foram:
    HashSet -> TreeSet -> TreeMap -> HashMap
  • Sobre a performasse das buscas, que eh a performasse que mais me interessa, todos foram muito rapidos, ou pelo menos naum tenho tanta memoria assim no meu pc para conseguir causar uma diferenca heheh.

Enfim, por isso queria usar Set (naum precisa nem ser TreeSet, assim naum preciso obrigar a definicao de um Comparator para estados), ele tem uma performasse de insercao melhor, consome menos memoria (segundo meus testes)… mas naum consigo retornar o key, entao imagino que vou ter que partir para a solucao HashMap<HashCode do estado, NohDaBusca> acho…

Eh isso ai, para isso que quero… pelo que conheco de java, naum consegui achar uma estrura melhor do que Set’s e Map’s para implementar a memoria da minhas buscas…

Valeu :wink: e naum me chamem de maluco, eh que essa eh a area da comp que eu gosto eheh muito mais do que ficar configurando xml’s para desenvolvimento web eheh :razz: [/code]

Criado 11 de outubro de 2006
Ultima resposta 13 de out. de 2006
Respostas 6
Participantes 3