Qual seria a melhor maneira para limpar um Arraylist que faz referência a outros Arraylist?
No meu caso é uma lista de Nós com suas arestas e eu preciso sempre limpar para abrir outros arquivos que variam a quantidade de Nós e arestas.
Eu imaginei algo assim:
[code]// Na classe CNo
public void inicializaArestas() {
listaArestas.removeAll(listaArestas);
listaArestas.clear();
}
// Na classe CGrafo
public void inicializaGrafo() {
CNo no;
while (listaNos.size() > 0) {
no = (CNo) listaNos.remove(0);
no.inicializaArestas();
no = null;
}
listaNos = new ArrayList(); // poderia usar o .clear ?
No meu caso, eu irei fazer um novo grafo, que será gerado através de um outro arquivo texto. Então como boa prática de programação, irei remover e limpar as arestas e os nós para que o gc remova os objetos e ao abrir o arquivo que contém um novo grafo, vou instânciando novos nós e arestas em outro método:
[code]// Na classe CNo
public void inicializaArestas() {
listaArestas.removeAll(listaArestas); // remove todas as arestas do nó
listaArestas.clear(); // limpa as arestas para que o gc remova os objetos
}
// Na classe CGrafo
public void inicializaGrafo() {
CNo no = null; // inicializa a referência como nulo
while (listaNos.size() > 0) { // verifica se contém objetos
no = (CNo) listaNos.remove(0); // passa a referência antes de remover o objeto
no.inicializaArestas(); // remove todas as arestas do nó e instância novamente
no = null; // deixa preparado para gc limpar
}
listaNos.clear(); // limpa a lista de nós para o gc
Então só o .removeAll() seria o suficiente na classe CNo, assim como eu removendo os Nós pelo .remove, não é necessário o .clear no final da classe CGrafo, correto?
Então só o .removeAll() seria o suficiente na classe CNo, assim como eu removendo os Nós pelo .remove, não é necessário o .clear no final da classe CGrafo, correto?
E os comentários que fiz estão corretos?
[/quote]
O .clear não é necessário. Foi o que o ViniGodoy falou…
Sobre os comentários, só na linha 13: vai remover todas as arestas e instanciar novamente? Não vai só remover todas as arestas?
Também seria desnecessário fazer no = null naquela situação. A variável no é local, logo, ela será automaticamente deletada assim que a função sair. De qualquer modo, cada novo no atribuido irá sobrescrever a referência anterior, e tornar o no também passível de deleção.
Acho que você está meio obsecado pelo garbage collector… hehehheheh
É bom se perguntar sempre se é necessário nulificar variáveis. Essa prática é mais do que louvável e deveria ser feito por todos.
Entretanto, se as reposta for não, não coloque código extra redundante “só para garantir”.
Seu código mesmo fica resumido a:
public void inicializaArestas() {
listaArestas.clear(); // limpa as arestas para que o gc remova os objetos
}
// Na classe CGrafo
public void inicializaGrafo() {
listaNos.clear(); // limpa a lista de nós para o gc
}
Outra coisa. Sua variável CNo só é usada dentro do while.
Portanto, não a crie fora do while. Isso aumenta o escopo da variável desnecessariamente, e não melhora a performance do seu código.
Embora aquele while seja descenessário, se for fazer um while com variáveis locais, faça assim:
while (listaNos.size() > 0) { // verifica se contém objetos
CNo no = (CNo) listaNos.remove(0); // passa a referência antes de remover o objeto
no.inicializaArestas(); // remove todas as arestas do nó e instância novamente
}
Outra coisa.
Por que a sua listaNos não usa os generics? Use-os e evite aquele cast!
Cast são operações extremamente inseguras. Com a lista declarada usando generics, o mesmo while poderia ficar assim:
while (listaNos.size() > 0) { // verifica se contém objetos
listaNos.remove(0).inicializaArestar(); // passa a referência antes de remover o objeto
}
É claro que não há muito sentido em inicializar arestar de um nó que será excluído, como bem falou o colega. Por isso só o clear já seria suficiente.
hahaha…
Para quem está saindo de VB6. E via sua memória só aumentando e nunca diminuindo quando fechava um form.
Eu imaginava que era necessário atribuir null a no, para passar uma nova referência e tb o receio do garbage collector de não coletar.
Mas obrigado pelas dicas. Vou acabar usando mesmo generics. É que estou mais acostumado a trabalhar com ArrayList sem generics e como tenho que entregar esse trabalho semana que vem, nem pensei em generics.
O meu código resumido sem generics ficará na verdade assim, correto?:
[code]// Na classe CNo
public void inicializaArestas() {
listaArestas.clear(); // limpa as arestas para que o gc remova os objetos
}
// Na classe CGrafo
public void inicializaGrafo() {
listaNos.inicializaArestas(); // método para limpar as arestas de nó
listaNos.clear(); // limpa a lista de nós para o gc
}[/code]
e com generics, poderia fazer assim?:
[code]// Na classe CNo
public void inicializaArestas() {
listaArestas.clear(); // limpa as arestas para que o gc remova os objetos
}
// Na classe CGrafo
public void inicializaGrafo() {
listaNos.clear().inicializaArestas(); // limpa a lista de arestas e nós para o gc
}[/code]
Bem, pelo que eu entendo, se eu destruir apenas os nós, as arestas continuarão apontando para seus objetos. E com isso o gc(eu de novo com o garbage collector. rsrs) não irá coletar.
Se o nó for coletado, as arestas ficarão sem ninguém apontando para elas. E então serão coletadas. Os objetos apontados por elas imediatamente ficarão sem ninguém apontando para eles… e serão coletados. E por aí vai, até que tudo o que só tinha como vínculo o nó seja coletado.
Bem, é que eu entendo que os objetos nós seriam coletados, mas os objetos arestas não seriam, pois a listaAresta continuam apontando para eles, não é isso?
Obs.: Na especificação do trabalho, existem os métodos inicializaGrafo() e inicializaArestas(), então eu entendo que devo limpar a minha listaArestas da classe CNo e minha listaNos da classe CGrafo.
No meu caso, existe as seguintes classes:
CGrafo -> CNo -> CAresta
Sim, mas a partir do momento que vc limpa todos os nós (com o clear), as arestas vão no embalo.
A menos que haja ainda outra classe referenciando arestas, que não os nós.