Duvida na LinkedList Java

_coelhinha_

Power Member
Boas,

Tou com um pequeno problema, estou a fazer 1 programa que implementa linkedlist's e quando tento imprimir a lista ela imprime apenas o ultimo elemento que foi inserido sabem-me explicar porque? eu tenho uma classe do tipo Lobo que tem como metodos o nome e o ano e o toString depois noutra classe, classe principal do programa, crio o Lobo e ainda crio 1 lista do tipo Lobo onde insiro as coisas e é lá que tento imprimir mas como disse isto imprime sempre a ultima entrada...será dos metodos nome e ano?? Obrigado. :)
 
Construtor:
this.lobo = new Lobo ();
this.pos = new LinkedList <Lobo> ();

Um dos metodos da classe lobo (o do ano é igual):
public String nome (){
System.out.print("Introduza nome: ");
Scanner nomeLeitor = new Scanner(System.in);
return nome = nomeLeitor.next();
}

Inserçao dos dados:
public void novoLobo(){
String gps = new String ("Lobo");
lobo.nome();
try{
lobo.anoNascimento();
}
catch (InputMismatchException io){
System.out.println ("ERRO!!! O ano e' um inteiro!");
}
status.add(gps);
pos.add(index,lobo); /* Criei a treta do index para ver se ele criava no index a seguir*/
index++;
}

Metodo para imprimir na class principal:
public void listar (){

System.out.println(pos + " " + status + " " + posicionavel);
}

Aqui está os bocados de codigo que acho que sao os importantes :) tive de volta disso ate ás 5 da manha e mesmo agora ainda nao vi o problema lol Obrigado :)
 
hum, nao vi com muita atenção o que poderá ser outra coisa.
Tu tens varios objectos do tipo Lobo guardados na lista ligada, correcto?

Esse método listar deveria ser um iterador que ia imprimindo cada célula da lista. Dessa forma nao estas a iterar os elementos todos :x. Nem sabia que mandando imprimir o apontar pos da lista mandava o ultimo elemento, pensava que mandava um endereço um pouco estranho :x.
Todavia, o código esta um pouco confuso.
Daqui a um pouco vou tentar ver com melhor atenção. Mas o que me salta à vista é esse System.out.println(pos + ...);
Devias ter um iterador ou um ciclo for a percorrer a lista:
for( int i = 0 ; i < pos.size() ; i++)
Lobo l = pos.get(i) ou pos.next();
System.out.println(l.toString() + ...);

Nao sei como tens a tua lista implementada :x.

Cumps ;).
 
Sim eu sei que o codigo tá um bocado confuso...é que eu neste momento estou a tentar optimizar o codigo mas com esse problema nao me deixa avançar...continuando nem com o iterador vai lá lol vou passar ja o codigo 1 bocado + limpo lol
 
Metodo Listar:
/**
* Opcao LISTAR
*/
public void listar (){
Iterator <Lobo> it = lobos.iterator();
while(it.hasNext())
System.out.print(it.hasNext());
}



Metodo novo lobo:


/**
* Opcao NOVO_LOBO,
* cria um novo lobo
*/
public void novoLobo(){
String gps = new String ("Lobo");
lobo.setNome();
try{
lobo.anoNascimento();
}
catch (InputMismatchException io){
System.out.println ("ERRO!!! O ano e' um inteiro!");
}
status.add(gps);
lobos.add(lobo);
}
 
Esse código está um pouco feio com mistura de I/O e camada computacional. Aquilo que eu aconselhava era teres um segundo construtor que aceitasse como parâmetros uma string e um inteiro, os quais serviriam para inicializar as variáveis de instância da classe Lobo, nomeadamente nome e ano:

Código:
public class Lobo {
private String nome;
private int ano;

public Lobo() { this("",0); }
public Lobo(String nome, int ano) { this.nome = nome; this.ano=ano; }
Depois na classe principal terias a LinkedList<Lobo>, onde colocarias instâncias de Lobo com os valores lidos através do teclado:

Código:
public class Main {
Scanner input = new Scanner(System.in);
LinkedList<Lobo> lista = new LinkedList<Lobo>();
nome = input.nextLine();
ano = input.nextInt();
Lobo lobo1 = new Lobo(nome,ano);
lista.add(lobo1);
// e assim sucessivamente
E depois para mostrar os elementos da lista, podes iterar sobre a lista com um for:
Código:
for (Lobo l : lista)
System.out.println(l);
Sendo invocado o método toString da classe Lobo, o qual também poderias definir na classe Lobo:
Código:
public String toString() {
return "Lobo\n\tNome: " + this.nome + "\tAno: " + this.ano;
}
 
É impressao minha ou esse é o mesmo codigo mas apenas + bonitinho? pelo que percebi a diferença é que tens un segundo construtor...um construtor para inicializar as variaveis e outro para atribuir os valores ás variaveis
 
Não só está mais bonito como está mais correcto do ponto de vista de desenvolvimento de software. O teu código misturava camada de I/O com camada de computação de dados. Usando o teu código, se eu um dia quisesse fazer um menu interactivo com Swing para introduzi o nome e ano do lobo, teria de alterar quer a classe principal, quer a classe Lobo, pois na classe Lobo, fazes leitura de dados do teclado e isso não deve ser feito (deve ser feito apenas em classes dedicadas exclusivamente ao tratamento de I/O), enquanto que usando as minhas classes, apenas teria de criar a classe de interacção, sem alterar mais nada.
 
Bgd pela ajuda mas de qualquer maneira isso nao me resolve o problema lol isto ainda imprime sempre os mesmos dados =S de qualquer maneira o que tu fizeste ainda nao é o objectivo do trabalho lol mas bgd na mesma ;)
 
public void listar (){
Iterator <Lobo> it = lobos.iterator();
while(it.hasNext())
System.out.print(it.hasNext());
}

hum, nao é o hasNext() :x, esse é um método que retorna um booleano true se tem next.
deveria ser:
while(it.hasNext())
Lobo l = it.next();
System.out.println(l.toString());

O que o Baderous disse é verdade, ganha o habito de separar I/O da computação. I/O tratas apenas no Main.

String gps = new String ("Lobo");
lobo.setNome();

um "setter" deve ter um parâmetro. Ou estas a Fazer isso na classe Lobo? :x. E o new String é desnecessário. Faz apenas String gps = "Lobo";
Para que serve o status?

Mete o código de inserção na lista :x.
[EDIT]: e ja agora tens o iterador das listas implementado? Mete a classe LinkedList<E> aqui, sff ;).

;).
 
Ok essa do hasNext foi má..vi mal LOL agora o main nao posso alterar porque ja é fornecido pelo prof. O Status é uma flag que permite dizer se o lobo ja tem gps ou nao lol foi a melhor maneira que encontrei de fazer LOL o setNome faço na class lobo é errado? lool Tenho que implementar outro iterador para alem daquele? é porque as listas ja o têm lol

isto é a classe Lobo é so isto que tnho LOL

public class Lobo {

/**
* Guarda o nome dado pelo utilizador
*/
private String nome;

/**
* Guarda o ano dado pelo utilizador,
* referente a um lobo
*/
private int ano;

public Lobo(){
this.nome = nome;
this.ano = ano;
}

public String setNome (){
System.out.print("Introduza nome: ");
Scanner nomeLeitor = new Scanner(System.in);
nome = nomeLeitor.next();
return nome;
}

public int anoNascimento (){
System.out.print("Introduza ano: ");
Scanner intLeitor = new Scanner(System.in);
ano = intLeitor.nextInt();
return ano;
}

public String getNome (){
return nome;
}

public int getAno (){
return ano;
}

public String toString () {
return nome + "/" + ano;
}
}
 
Essa classe está feiinha. Isso pode complicar-te a vida (já complica).
O ideal é criares um par de objectos: um que representa o lobo, com os seus atributos (as variáveis privadas), métodos set e get (setNome(String nome), setAnoNascimento(int ano), getNome(), getAnoNascimento()), e o toString(), onde imprimes o nome e a data de nascimento.

Terias depois outro objecto para criar objectos do tipo Lobo, onde pedes duas coisas: nome e data de nascimento.

Quando tiveres isso, é mais fácil criares objectos Lobo, e adicioná-los à tal lista que falas (arraylist, suponho).

Para iterares sobre cada objecto dessa lista só precisas de fazer o que o Baderous disse:

Código:
for (Lobo l : lista)
  System.out.println(l);

Supondo que lista é um objecto do tipo ArrayList<Lobo> LinkedList<Lobo>.
É isso.

PS: já vi que é uma linkedlist, mas é indiferente. É válido na mesma.
 
Última edição:
Isso do gps é inutil. Na classe Lobo poderias ter mais um atributo:
boolean gps;

em que punhas a true se ja tem gps ou false caso contrario.
Esses set's nao parecem muito correctos :x. se tens o getNome() os set's deveriam ser do tipo void setNome(String nome){ this.nome = nome; }

E na classe Main fazias um metodo publico que recebia essa informação do Scanner fazias o setNome(String nome) ou passavas logo no constructor. Poupava complicações, acredita.
Em relação à listagem das coisas, de facto, podes fazer como foi dito em cima.
fazes um l.toString :x.

Se o problema persistir deverá ser as listasligadas :x.
Manda o prof passear xD, nao podes alterar o que ele da mas podes acrescentar :rolleyes:.
 
Muito obrigado pelas dicas =P graças ás vossas dicas realmente o codigo tem ficado + simples ...mas nem com iterador nem com for each consigp imprimir os varios lobos LOLOLOLOL

vou mostrar um output do trabalho LOL :


Introduza uma opcao: novo_lobo
Introduza nome: maria
Introduza ano: 2001
Introduza uma opcao: listar
maria/2001
Introduza uma opcao: novo_lobo
Introduza nome: fojo
Introduza ano: 2003
Introduza uma opcao: listar
fojo/2003
fojo/2003


EDIT: e fiz algo do genero que me disseram para fazer mas nao me simplificou muito a vida lool
 
Última edição:
Código:
[B]Construtor:[/B]
this.lobo = new Lobo ();
this.pos = new LinkedList <Lobo> ();

[B]Um dos metodos da classe lobo (o do ano é igual):[/B]
public String nome (){
        System.out.print("Introduza nome: ");
        Scanner nomeLeitor = new Scanner(System.in);
        return nome = nomeLeitor.next();
    }

[B]Inserçao dos dados:[/B]
    public void novoLobo(){
        String gps = new String ("Lobo");
        lobo.nome();
        try{ 
            lobo.anoNascimento();
        }
        catch (InputMismatchException io){
            System.out.println ("ERRO!!! O ano e' um inteiro!");
        }
        status.add(gps);
        pos.add(index,lobo); /* Criei a treta do index para ver se ele criava no index a seguir*/
        index++;
    }
Tira a iniciação da variavel lobo do construtor. E mete dentro do método novoLobo.
Aliás esta variável não deveria ser variável da classe. Deveria ser só declara dentro do método. O teu problema está relacionado à manipulação desta variável.
 
/**
* Opcao LISTAR
*/
public void listar (){
for (Lobo l : lobos)
System.out.println(l + " " + gps());
}

private String gps (){
return status ? "LoboComGps" : "Lobo";
}

Isto imprime supostamente a lista

----------------------------------------------

public void setNome (String nome){
this.nome = nome;
}

public void anoNascimento (int ano){
this.ano = ano;
}

public String getNome (){
return nome;
}

public int getAno (){
return ano;
}

public String toString () {
return nome + "/" + ano;
}

cá está o codigo que faz a insercao dos dados e dps faço lobos.add(lobo); para adicionar ;)
 
De facto foi uma boa visão essa da instancia do objecto.
Agora os porquês. Se declarares uma variavel global à classe e nao a reinicializares vais estar sempre a modificar o proprio objecto.

Hum, apaga essa variavel. E mete-a so no método. Hum, mete aqui o teu código todo onde inseres. Poderás estar a usar a variavel algures e quando apagas estoira.
 
Back
Topo