• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Baderous

Problema com construtor

14 mensagens neste tópico

Cá estou eu com mais uma dúvida. Desta vez tenho uma classe que tem um TreeSet<Passageiro> como variável de instância, sendo Passageiro uma classe que tem 3 Strings como variáveis de instância. Estou a tentar definir um construtor na sua forma mais básica receberia um TreeSet<Passageiro> e um Comparator de Passageiros, o qual já defini numa classe à parte. Disse forma mais básica pois estou a tentar obter o máximo de abstracção, fazendo por isso com que o tal TreeSet que é argumento seja na verdade uma Collection<? extends Passageiro>. O método compila e acho que está bem definido, mas quando, numa classe de teste tento criar um conjunto de passageiros através deste construtor dá-me erro.

Classe que implementa o Comparator de Passageiros:

import java.util.*;
import java.io.*;

public class PassageiroComparator implements Serializable, Comparator<Passageiro> {
    /**Método que compara 2 Passageiros pelos seus códigos*/
    public int compare(Passageiro p1,Passageiro p2) {
        return (p1.getCodigo()).compareTo(p2.getCodigo());
    }
}

Classe que implementa o TreeSet<Passageiro>:

import java.util.*;
import java.io.*;

public class ListaPassageiros implements Serializable {
    //Variáveis de instância
    /**Conjunto de passageiros de um voo*/
    private TreeSet<Passageiro> listaP;

/**Construtor que recebe um Comparator*/
    public ListaPassageiros(Comparator<Passageiro> c) {
        listaP = new TreeSet<Passageiro>(c);
    }
    
    /**Construtor completo*/
    public ListaPassageiros(Collection<? extends Passageiro> lst, Comparator<Passageiro> c) {
        this(c);
        for (Passageiro p : lst)
            listaP.add(p.clone());
        }

Classe de teste:

public class Teste {
    public static void main(String[] args) {
        ListaPassageiros lista = new ListaPassageiros();
        Passageiro p1 = new Passageiro("q123","joao","pt");
        Passageiro p2 = new Passageiro("a423","maria","esp");
        Passageiro p3 = new Passageiro("23sdf","jose","nam");
        lista.inserePassageiro(p1);
        lista.inserePassageiro(p2);
        lista.inserePassageiro(p3);
ListaPassageiros lesp = new ListaPassageiros(lista,new PassageiroComparator());

O erro ocorre nesta última linha. Consultando a ajuda do BlueJ, ele indica:

72177366gf4.jpg

Também tenho um erro de compilação quando uso um método semelhante que adiciona uma colecção de passageiros ao conjunto já existente.

/**Método que adiciona uma colecção de passageiros ao conjunto já existente*/
    public void insereColeccao(Collection<? extends Passageiro> c) {
        for (Passageiro p : c)
            listaP.add(p.clone());
        }

Alguma coisa devo estar a fazer mal...

Não creio que o erro esteja no Collection<? extends Passageiro> porque já tentei fazer com TreeSet<Passageiro> e dá erro na mesma. Deve ser problema na classe de teste...

Somebody help me!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não te posso ajudar com o teu problema mas visto isto ser relacionado com o trabalho que também estou a fazer, porquê que estas a usar um TreeSet para a lista de passageiros? Será que vais tirar partido da ordenação do TreeSet? Em que circunstâncias?

Mas o mais importante é, porque não um Map onde ao código do passageiro associas-lhe a ficha de passageiro? Pelo menos é como eu estou a fazer e parece ser uma hipotese melhor do que simplesmente guardar as fichas sem lhe associares nada. Claro que isto depende um pouco de como irás fazer o resto do trabalho e das operações que vais efectuar à lista de passageiros, mas assim há primeira vista, parece-me melhor um Map (seja Hash ou Tree, isso já é + especifico).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Porque tendo em conta as operações que vão ser efectuadas sobre os passageiros, não será necessário consultar a informação pessoal de cada um. Eu por acaso também pus essa ideia no início mas depois fiz com Set, só para evitar repetidos.

Quanto ao meu problema, acho que já resolvi. O problema era que estava a passar uma instância de ListaPassageiros no lugar de uma Collection, logo dava erro.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Quanto ao meu problema, acho que já resolvi. O problema era que estava a passar uma instância de ListaPassageiros no lugar de uma Collection, logo dava erro.

Raios, tinha respondido isto para só depois ver que tinhas resolvido o problema. Tenho de aprender a ler com mais atenção :P

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Vou aproveitar esta thread para perguntar sobre uma coisa parecida. Quero criar uma classe que tem como variável de instância um Map<CodigoDeVoo,Voo>. Voo possui um tempo de partida como variável. Eu gostava que esse Map fosse um TreeMap<CodigoDeVoo,Voo> em que os códigos estivessem ordenados por tempo de partida dos voos. Mas isto não é possível pois não uma vez que a ordenação é referente às chaves do Map, certo?

Se não for, como devo fazer? Criar um HashMap<CodigoDeVoo,Voo>, e depois num método auxiliar, criar um TreeMap que seja cópia deste HashMap, mas que esteja ordenado por TempoPartida??

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A ordenaçã é sempre feita pela chave, usando apenas uma estrutura não consegues ordenar os elementos sem ser por chave.

Outro problema a que tens de ter atenção é que é perigoso usar, como chave, elementos que não são imutáveis, isto é, uma chave não deve sofrer alterações que afectem o método equals, enquanto está dentro de um Map. Se isso acontecer, o comportamento do Map é indeterminado.

Quanto ao teu problema, a solução que apresentaste é uma possível, mas precisas que os elementos estejam sempre ordenados por tempo ou a ordenação acontece em alturas muito especificas?

Se não precisas sempre poderás usar os métodos de ordenação da classe Collections, desta forma ordenas apenas quando precisas dos dados por ordem e não tens uma segunda estrutura. Tens a desvantagem de perder alguma performance, mas pode ser mais simples de implementar.

Por outro lado, se usares o TreeMap e tiveres dois tempos iguais? Repara que ao adicionares dois objectos diferentes com a mesma chave, o valor antigo é substituído.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A ordenaçã é sempre feita pela chave, usando apenas uma estrutura não consegues ordenar os elementos sem ser por chave.

Tal como suspeitava.

Outro problema a que tens de ter atenção é que é perigoso usar, como chave, elementos que não são imutáveis, isto é, uma chave não deve sofrer alterações que afectem o método equals, enquanto está dentro de um Map. Se isso acontecer, o comportamento do Map é indeterminado.

Por outro lado, se usares o TreeMap e tiveres dois tempos iguais? Repara que ao adicionares dois objectos diferentes com a mesma chave, o valor antigo é substituído.

Ainda bem que disseste isso, pois a variável Tempo de Partida pode sofrer alterações (atrasos no voo), e podem existir 2 voos à mesma hora!

Quanto ao teu problema, a solução que apresentaste é uma possível, mas precisas que os elementos estejam sempre ordenados por tempo ou a ordenação acontece em alturas muito especificas?

Se não precisas sempre poderás usar os métodos de ordenação da classe Collections, desta forma ordenas apenas quando precisas dos dados por ordem e não tens uma segunda estrutura. Tens a desvantagem de perder alguma performance, mas pode ser mais simples de implementar.

O objectivo da classe é guardar o mapa de voos do aeroporto. Não creio que seja necessário ter os voos por ordem. No entanto, um dos requisitos é que deverá existir um Placard electrónico no aeroporto que apresente informação relativa a alguns voos e têm de estar por ordem de tempo de partida.

Mas agora estou aqui a pensar...se eu criar uma classe VooComparator que implemente a interface Comparator<Voo>, onde, se o tempo de partida do voo v1 for menor do que o v2, então ele é menor, caso contrário (se for igual ou maior), então é maior. Algo como isto (tempo de partida é instância de GregorianCalendar):

public class VooComparator implements Serializable, Comparator<Voo> {
    /**Método que compara 2 Tempos de Partida pelas suas horas*/
    public int compare(Voo v1,Voo v2) {
        if (v1.getTempoPartida().before(v2.getTempoPartida()))
            return -1;
        else return 1;
    }
}

Assim já poderei fazer o tal método com o TreeMap, passando-lhe o Comparator como parâmetro (desde que, quando ocorra um atraso, remova a chave e o Voo do Map, altere o tempo de partida, e volte a inserir)?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podes fazer isso, mas se apenas precisas de dados organizados numa determinada situação, porque não organizar os dados nessa altura?

Já agora, essa implementaçã de comparação está incompleta, não contemplas a situação de serem tempos iguais. Um comparador devolve < 0, 0 ou > 0.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Então uso os métodos de ordenação da classe Collections? E quais são eles (não estou por dentro desta classe)?

public static <T> void sort(List<T> list, Comparator<? super T> c)

Este?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sim, podes usar esses, ou esse, método de ordenação.

Se usares o sort que recebe um comparador podes usar o que já tens feito ou fazer outro que se adapte melhor, se não quiseres usar um comparador podes colocar os teus objectos a implementarem a classe Comparable, que é o mesmo que o comparador, e podes usar o método sort que recebe apenas uma Collection.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não querem dar um exemplo mais concreto de como se faria isso? Também vou precisar disto :thumbsup: mas não estou a ver bem como faria, ainda não domino bem o comparator...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Um pequeno exemplo de como usar a interface Comparable e o método sort da classe Collections para ordernar uma lista.

Se usarem um comparador terão de usar o método que receba o comparador e adaptar em conformidade. Em principio será apenas retirar a interface e o método de comparação.

Reparem que usando a interface Comparable apenas podemos comparar de uma forma, não sendo possível ter dois métodos de comparação.

package allaroundtesting;

import java.util.Collections;
import java.util.LinkedList;

/**
*
* @author knitter
*/
public class Pessoa implements Comparable {

    private String nome;
    private int idade;
    private LinkedList<Pessoa> familiares;
    
    public Pessoa() {
        familiares = new LinkedList<Pessoa>();
        familiares.add(new Pessoa("Tiago", 50));
        familiares.add(new Pessoa("Joao", 15));
        familiares.add(new Pessoa("Andre", 35));
        familiares.add(new Pessoa("Maria", 20));
        familiares.add(new Pessoa("Ana", 35));
        familiares.add(new Pessoa("Marta", 40));
        familiares.add(new Pessoa("Jose", 10));
        familiares.add(new Pessoa("Paula", 5));
    }
    
    public Pessoa(String nome, int idade) {
        this.nome = nome;
        this.idade = idade;
    }
    
    public void mostrar() {
        System.out.println("Antes de ordenar:");
        for(Pessoa p : familiares) {
            System.out.println(p);
        }
        
        Collections.sort(familiares);
        
        System.out.println("\nDepois dede ordenar:");
        for(Pessoa p : familiares) {
            System.out.println(p);
        }        
    }
    
    //Comparar por nome para que as pessoas possam ser ordenadas por nome.
    public int compareTo(Object o) {
        return nome.compareTo(((Pessoa) o).nome);
    }
    
    //Comparar por idade, apenas um metodo de comparacao pode existir
    /*
    public int compareTo(Object o) {
        idade - ((Pessoa)o).idade;
    }*/
    
    @Override
    public String toString() {
        return nome + ", " + idade + " anos.";
    }
    
    public static void main(String[] args) {
        new Pessoa().mostrar();
    }
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Acho que já consegui. Criei um método onde tenho 1 ArrayList<GregorianCalendar> e um HashSet<Voo> e um ArrayList<Voo>. Depois percorro o mapa de voos e coloco os tempos de partida de cada voo no ArrayList<GregorianCalendar> e os voos no HashSet<Voo>. Depois faço Collections.sort do ArrayList<GregorianCalendar>, ficando os tempos ordenados por ordem crescente. Depois, percorro esse ArrayList e, para cada tempo, vou ao HashSet<Voo> buscar o voo cujo tempo de partida lhe corresponde, coloco-o no ArrayList<Voo> e retiro-o do HashSet<Voo> (assim quando ele vai procurar por um tempo de partida repetido, vai-me devolver outro voo, não interessa a ordem, o que interessa é que não sai o mesmo, porque já lá não está). Por fim devolvo o ArrayList<Voo>.

/**Método que ordena os voos por Tempo de Partida*/
    public List<Voo> ordenaPorTempo() {
       ArrayList<GregorianCalendar> tp = new ArrayList<GregorianCalendar>();
       HashSet<Voo> voos = new HashSet<Voo>();
       ArrayList<Voo> res = new ArrayList<Voo>();
       for (Voo v : this.mapa.values()) {
            tp.add(v.getTempoPartida());
            voos.add(v.clone());
        }
       Collections.sort(tp);
       for (GregorianCalendar c : tp) {
            boolean encontrado = false;
            Iterator<Voo> it = voos.iterator();
            Voo v = null;
            while (!encontrado && it.hasNext()) {
                v = it.next();
                if (v.getTempoPartida().equals(c)) {
                    encontrado = true;
                    res.add(v.clone());
                    it.remove();
                }
            }
        }
        return res;
    }

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Bem, dado que me parece já teres o problema resolvido não há muito mais a dizer ;)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora