Problema ArrayList como parametro

44 respostas
A

Estou passando um objeto da classe ArrayList como parametro e alterando esse objeto dentro do método. O problema é que essa alteração se reflete também na referência desse objeto que está fora do método. Alguém sabe como modificar um objeto sem interferir na sua referência ou como criar um objeto que não tenha referência?

A declaração do método é assim:

public ArrayList<Pesquisador> retornarPesquisadores(ArrayList<Pesquisador> lista)

Dentro desse método eu removo alguns elementos do parametro lista. Porém, essa alteração também é refletida no argumento que foi passado para o método…

44 Respostas

P

vc quer q a alteração não afete o que foi passado como parametro?
nao tenho certeza, mas ja testou utilizar o clone e alterar o novo objeto?

B

Impossível.

Crie um novo objeto, passe todos os dados de um objeto para este novo, e passe a trabalhar com ele.

mario.fts

Tente assim dentro do método:

List<Pesquisador> listaNova = new ArrayList<Pesquisador>().addAll(lista);

trabalhe com a lista nova.

Até

souzaJr
import java.util.ArrayList;

public class Teste {
	
	public void alteraLista(ArrayList<Integer> l){
		l.add(3);
		l.add(4);
	}
	
	public static void main(String a []){
		ArrayList<Integer> l = new ArrayList<Integer>(0);
		l.add(1);
		l.add(2);
		Teste obj = new Teste();
		obj.alteraLista(new ArrayList<Integer>(l));
		for(Integer i : l){
			System.out.println(i);
		}
	}
}

Dá uma olhada sobre passagem de parâmetros em Java. Aqui no forum tá cheio de discussão sobre isso.

Até mais.

A

o meu método é assim:

public ArrayList<Pesquisador> retornarPesquisadores(ArrayList<Pesquisador> lista, char tipo) 
{
 ArrayList<Pesquisador> lp = new ArrayList<Pesquisador>();

 for (Pesquisador p : lista)
 {
  ArrayList<PosGraduacao> aux = (ArrayList<PosGraduacao>)p.retornarPosGraduacoes();
 
  Iterator i = aux.iterator();

  while (i.hasNext())
  {
    PosGraduacao pg = (PosGraduacao)i.next();

    if (pg.getTipo() == tipo)
    {
     if (!lp.contains(p))
      lp.add(p);
     } else
         i.remove();
   }
 }  
 return lp;
}

E o como já disse, o argumento passado para o método é afetado pelo parametro lista...

B

Para quê o i.remove()?

A

porque tenho várias pos-graduações (mestrado, doutorado…) e quero remover todas que não sejam do tipo que estou pasando no método

B

Você está fazendo um método que filtra uma lista e retorna uma nova, não tem por que alterar a lista passada por parâmetro.

Portanto só passe os objetos que você quer para a nova lista, não mexa na lista anterior.

A

Você está fazendo um método que filtra uma lista e retorna uma nova, não tem por que alterar a lista passada por parâmetro.

Portanto só passe os objetos que você quer para a nova lista, não mexa na lista anterior.

Eu não estou alterando a lista passada. Eu estou removendo uma pos-graduacao do pesquisador, que é um dos objetos da lista… Eu publiquei o código, se puder dar uma olhada, eu agradeço…

B

Confusão....

Se você quer remover todas que não são do tipo que está passando por parâmetro, adicione todos que são do tipo que você está passando.

public List<Pesquisador> filtrarPorPosGraduacao(List<Pesquisador> lista, PosGraduacao pos) 
{
  List<Pesquisador> lp = new ArrayList<Pesquisador>();

  for (Pesquisador p : lista)
  {
    List<PosGraduacao> aux = p.retornarPosGraduacoes();
 
    if (aux.contains(pos))
      lp.add(p);

  }  
  return lp;
}
A

o meu problema não está no filtro. O código está filtrando corretamente…

O problema é que o objeto lista passado como parametro também está sendo alterado, sendo que no método eu não mexo nesse objeto.

B

Não vejo nenhum lugar que a lista esteja sendo alterada.

De quê forma a lista está sendo alterada? O tamanho dela muda? A posição dos objetos muda? Como você percebeu o bug?

ViniGodoy

Se está sendo alterado, você com certeza mexe no objeto. Adicione um breakpoint nos métodos do seu objeto e rode com um depurador.

A

Bruno Laturner:
Não vejo nenhum lugar que a lista esteja sendo alterada.

De quê forma a lista está sendo alterada? O tamanho dela muda? A posição dos objetos muda? Como você percebeu o bug?

o problema é que quando a linha i.remove(); é executada ela altera a lista. Acho que é por causa da referência com o objeto lista…

mario.fts

Sim… é por causa da referência.

mas se vc não passa a lista de pos-graduação para fora do método, e não quer que ela seja alterada, pra que vc usa o remove()?

B

remove retira o objeto pósgraduação da lista de pósgraduações.

o problema dele é a lista de pesquisadores, esta que não deveria ser mexida.

A

mario.fts:

o problema é que quando a linha
i.remove();
i.remove(); é executada ela altera a lista. Acho que é por causa da referência com o objeto lista…

Sim… é por causa da referência.

mas se vc não passa a lista de pos-graduação para fora do método, e não quer que ela seja alterada, pra que vc usa o remove()?

Eu não quero que o objeto lista seja alterado (por causa da referencia), mas eu quero alterar a lista de pos-graduacao. Acho que eu teria que criar uma cópia dessa lista e mexer na cópia. Já tentei com o método clone(), mas ele também cria uma referência… Não sei o que fazer???

A

Bruno Laturner:
remove retira o objeto pósgraduação da lista de pósgraduações.

o problema dele é a lista de pesquisadores, esta que não deveria ser mexida.

Exatamente isso !!! Tem alguma idéia de como resolver isso??? o método clone também cria uma referência…

mario.fts

se vc quer criar uma cópia da lista, crie um novo objeto e adicione todos os elementos da lista original nele:

ArrayList<PosGraduacao> aux = new ArrayList<PosGraduacao>();

aux.addAll(p.retornarPosGraduacoes());

mas ainda não vejo o pq do remove… :wink:

lcegatti

Tente isto:

List<Pesquisador> listaNova = new ArrayList<Pesquisador>();
Collections.copy(listaNova , lista);

[]'s

ViniGodoy

Não basta só retirar essa linha do remove?

Aliás, o remove não altera o objeto da lista. Só a lista.

Se está alterando, há um erro no seu código do objeto. Provavelmente no método equals ou hashcode.

A

mario.fts:
mas ainda não vejo o pq do remove… :wink:

é que tenho varios tipos de pos-graduacao (mestrado, doutorado, pos-doutorado…) e quero filtrar apenas as pos-graduacoes de metrado, por exemplo. Então eu tenho que usar o remove…

A

lcegatti:
Tente isto:

List<Pesquisador> listaNova = new ArrayList<Pesquisador>();
Collections.copy(listaNova , lista);

[]'s

Lança a seguinte exceção: java.lang.IndexOutOfBoundsException: source does not fit in dest

lcegatti

adalves1:
lcegatti:
Tente isto:

List<Pesquisador> listaNova = new ArrayList<Pesquisador>();
Collections.copy(listaNova , lista);

[]'s

Lança a seguinte exceção: java.lang.IndexOutOfBoundsException: source does not fit in dest

List<Pesquisador> listaNova = new ArrayList<Pesquisador>(lista.size());
A

ViniGodoy:
Não basta só retirar essa linha do remove?

Aliás, o remove não altera o objeto da lista. Só a lista.

Se está alterando, há um erro no seu código do objeto. Provavelmente no método equals ou hashcode.

Na minha classe Pesquisador eu tenho apenas o método equals. O método hashcode eu não implementei. É necessário???

B

adalves1:
mario.fts:
mas ainda não vejo o pq do remove… :wink:

é que tenho varios tipos de pos-graduacao (mestrado, doutorado, pos-doutorado…) e quero filtrar apenas as pos-graduacoes de metrado, por exemplo. Então eu tenho que usar o remove…

Não, não tem.

Você cria uma nova List de pesquisadores, vê quem tem mestrado e adiciona esses à lista. Você não tem que mexer na lista de posgraduações.

A

lcegatti:
List<Pesquisador> listaNova = new ArrayList<Pesquisador>(lista.size());

continua com a mesma exceção…

A

Bruno Laturner:
adalves1:
mario.fts:
mas ainda não vejo o pq do remove… :wink:

é que tenho varios tipos de pos-graduacao (mestrado, doutorado, pos-doutorado…) e quero filtrar apenas as pos-graduacoes de metrado, por exemplo. Então eu tenho que usar o remove…

Não, não tem.

Você cria uma nova List de pesquisadores, vê quem tem mestrado e adiciona esses à lista. Você não tem que mexer na lista de posgraduações.

Eu tenho que mexer nas pos-graduacoes sim!!! é que um pesquisador pode ter mais de uma pos-graduacao, ou seja, cada pesquisador tem uma lista de pos-graduacoes e eu quero que ele retorne os pesquisadores com o tipo de pos-graduacao que eu passar para o metodo. Caso um pesquisador, por exemplo, tenha feito mestrado e doutorado, se eu pedir pra filtrar os mestrados, ele tem que remover o doutorado…

souzaJr
import java.util.ArrayList;
import java.util.Iterator;

public class Teste {

	public ArrayList<Aluno> retornarAlunoes(ArrayList<Aluno> lista, int nota){
		ArrayList<Aluno> lp = new ArrayList<Aluno>();
		for (Aluno p : lista){
			ArrayList<Double> aux = (ArrayList<Double>)p.notas;
			Iterator i = aux.iterator();
			Aluno novoAluno = new Aluno();
			ArrayList<Double> notasAceitaveis = new ArrayList<Double>();
			while (i.hasNext())
			{
				Double pg = (Double)i.next();
				if (pg > nota){
					notasAceitaveis.add(pg);
					if (!lp.contains(novoAluno)){
						novoAluno.notas = notasAceitaveis;
						lp.add(novoAluno);
					} 
				}	
			}
		}  
		return lp;
	}

	class Aluno{
		ArrayList<Double> notas;
	} 

	public static void main(String a []){
		Teste obj = new Teste();
		ArrayList <Double> n = new ArrayList<Double>();
		n.add(2.0);
		n.add(7.0);
		n.add(4.0);
		Aluno b = obj.new Aluno();
		Aluno novoAluno = obj.new Aluno();
		b.notas = n;
		ArrayList <Double> novasNotas = new ArrayList<Double>(n);
		novasNotas.remove(1);
		novoAluno.notas = novasNotas;
		ArrayList<Aluno> lista = new ArrayList<Aluno>();
		lista.add(b);
		lista.add(novoAluno);

		for(Aluno d : obj.retornarAlunoes(lista, 5)){
			for(Double e : d.notas){
				System.out.println(e);
			}
		}

		System.out.println("A lista antiga: ");
		for(Aluno d : lista){
			for(Double e : d.notas){
				System.out.println(e);
			}
		}
	}
}

Cara, pelo que eu entendi, você quer percorrer a lista e ir colocando em outra só os Pesquisadores que tiverem a pós-graduação que você passou ao método. Se ele tiver outra, não importa…no final sua lista vai conter como se o pesquisador só tivesse a pós-graduação que você determinou. É isso?

Eu fiz um exemplo aí…só troquei basicamento os tipos… o que tu podia fazer é criar uma cópia do objeto Pesquisador dentro do loop…aí você faz o que quiser com ele…e tira o i.remove();

Testa aí…

Até mais.

mario.fts

o que o Bruno Laturner disse está certo.

vc não precisa remover da lista só pra listar.

lcegatti

adalves1:
lcegatti:
List<Pesquisador> listaNova = new ArrayList<Pesquisador>(lista.size());

continua com a mesma exceção…

Mal errei em um detalhe, depois vc testa ai:

ArrayList<Pesquisador> listaNova = new ArrayList<Pesquisador>(lista);
Collections.copy(listaNova, lista);
B

O teu método recebe uma lista de pesquisadores, a filtra pela pos graduação que fizeram e retorna uma lista de pesquisadores.

Primeiramente você cria uma lista vazia de pesquisadores.

Agora para cada pesquisador, você obtem uma lista de posgraduações deles.

Com a lista em mãos, você verifica se uma dessas pós graduações é a que procura. Caso verdadeiro, você adiciona o pesquisador à lista vazia. Caso ele não tenha a pós graduação você não adiciona ele à lista de pesquisadores, ou seja, não faz nada.

Ao final você retorna a lista gerada de pesquisadores.

A

lcegatti:
Mal errei em um detalhe, depois vc testa ai:

ArrayList<Pesquisador> listaNova = new ArrayList<Pesquisador>(lista); Collections.copy(listaNova, lista);

O comando agora funciona… mas o problema continua. Valeu!!!

A

O teu método recebe uma lista de pesquisadores, a filtra pela pos graduação que fizeram e retorna uma lista de pesquisadores.

Primeiramente você cria uma lista vazia de pesquisadores.

Agora para cada pesquisador, você obtem uma lista de posgraduações deles.

Com a lista em mãos, você verifica se uma dessas pós graduações é a que procura. Caso verdadeiro, você adiciona o pesquisador à lista vazia. Caso ele não tenha a pós graduação você não adiciona ele à lista de pesquisadores, ou seja, não faz nada.

Ao final você retorna a lista gerada de pesquisadores.

É justamente isso que quero fazer. Acho que a implementação está correta, pois mando escrever a lista que foi retornada e está ok. o problema é que a referencia ao objeto lista é alterada também…

B

Por favor nos dê um exemplo detalhado do teu problema. Só conversando aqui não tá dando pra saber o que exatamente está sendo alterado.

souzaJr

É isso??

A

Por favor nos dê um exemplo detalhado do teu problema. Só conversando aqui não tá dando pra saber o que exatamente está sendo alterado.

O que está sendo alterado é o argumento que é referenciado pelo objeto lista.

A declaração do método é:

public ArrayList<Pesquisador> retornarPesquisadores(ArrayList<Pesquisador> lista, char tipo)

Quando chamo o método ArrayList<Pesquisador> retorno = objeto.retornarPesquisadores(pesquisadores, 'M'); o objeto pesquisadores é alterado. O objeto retorno está correto…

A

É isso??

Sim, é exatamente isso.

souzaJr

Então faz como eu postei no meu antepenúltimo post… Eu postei o código lá… só mudando os tipos.

Flw.

A
souzaJr:
Sim, é exatamente isso.

Então faz como eu postei no meu antepenúltimo post... Eu postei o código lá... só mudando os tipos.

Flw.


o código do método é:

public ArrayList<Pesquisador> retornarPesquisadores(ArrayList<Pesquisador> lista, char tipo)    
{   
 ArrayList<Pesquisador> lp = new ArrayList<Pesquisador>();   
  
 for (Pesquisador p : lista)   
 {   
  ArrayList<PosGraduacao> aux = (ArrayList<PosGraduacao>)p.retornarPosGraduacoes();   
    
  Iterator i = aux.iterator();   
  
  while (i.hasNext())   
  {   
    PosGraduacao pg = (PosGraduacao)i.next();   
  
    if (pg.getTipo() == tipo)   
    {   
     if (!lp.contains(p))   
      lp.add(p);   
     } else  
         i.remove();   
   }   
 }     
 return lp;   
}
A chamada ao método é:
ArrayList<Pesquisador> retorno = objeto.retornarPesquisadores(pesquisadores, 'M');

o problema é que o objeto pesquisadores passado no método também é alterado!!!!

souzaJr
for (Pesquisador p : lista)     
{     
  ArrayList<PosGraduacao> aux = (ArrayList<PosGraduacao>)p.retornarPosGraduacoes();     

}

Então, dentro desse for aí é que tu tem que criar uma cópia (cria um novo com as mesmos atributos) de Pesquisador… Para que quando tu possa fazer o que quiser com ele (inclusive fazer com que ele só tenha a pós-graduação que tu quiser). E tira o i.remove();

B

Isso já sabemos. Quero saber que tipo de alterações acontecem. Algum objeto some? O nome de um pesquisador muda? A lista de pós-graduações do pesquisador só tem uma pós quando deveria ser várias?

A

Isso já sabemos. Quero saber que tipo de alterações acontecem. Algum objeto some? O nome de um pesquisador muda? A lista de pós-graduações do pesquisador só tem uma pós quando deveria ser várias?

o objeto pesquisadores fica parecido com o retorno. Ele contém todos os dados do objeto retorno mais os pesquisadores que não fizeram mestrado.

A saída é +/- assim:

OBJETO PESQUISADORES = [cod= 1 nome= Joao pos=MD cod= 2 nome= Maria pos=M cod=3 nome=Jose pos='nao tem ']
OBJETO RETORNO = [cod= 1 nome= Joao pos=M cod= 2 nome= Maria pos=M]

Depois de executar o método, o objeto pesquisadores fica assim:

[cod= 1 nome= Joao pos=M cod= 2 nome= Maria pos=M cod=3 nome=Jose pos='nao tem ']

e deveria ser igual era antes!!!

B

A culpa é do i.remove(), ele remove as pós dos pesquisadores.

O problema é que a referencia dos objetos é copiado para a nova lista, e não uma cópia deles. Ou seja, se você muda o nome de um pesquisador, vai acontecer o mesmo no pesquisador na outra lista.

O mesmo acontece com as pós, elas estão sendo removidas do objeto pesquisador, se ele está dentro de uma lista ou outra não importa, ele é o mesmo objeto.

Uma solução é tirar o i.remove().

Criado 9 de outubro de 2008
Ultima resposta 9 de out. de 2008
Respostas 44
Participantes 7