Baderous Posted June 23, 2008 at 11:30 PM Report Share #193155 Posted June 23, 2008 at 11:30 PM 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: http://img183.imageshack.us/img183/949/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! Link to comment Share on other sites More sharing options...
Guest id194 Posted June 23, 2008 at 11:42 PM Report Share #193158 Posted June 23, 2008 at 11:42 PM 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). Link to comment Share on other sites More sharing options...
Baderous Posted June 23, 2008 at 11:47 PM Author Report Share #193159 Posted June 23, 2008 at 11:47 PM 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. Link to comment Share on other sites More sharing options...
Knitter Posted June 24, 2008 at 10:50 AM Report Share #193187 Posted June 24, 2008 at 10:50 AM 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 😛 www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Baderous Posted June 26, 2008 at 02:57 PM Author Report Share #193691 Posted June 26, 2008 at 02:57 PM 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?? Link to comment Share on other sites More sharing options...
Knitter Posted June 26, 2008 at 04:04 PM Report Share #193715 Posted June 26, 2008 at 04:04 PM 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. www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Baderous Posted June 26, 2008 at 04:22 PM Author Report Share #193721 Posted June 26, 2008 at 04:22 PM 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)? Link to comment Share on other sites More sharing options...
Knitter Posted June 26, 2008 at 04:28 PM Report Share #193727 Posted June 26, 2008 at 04:28 PM 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. www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Baderous Posted June 26, 2008 at 04:38 PM Author Report Share #193731 Posted June 26, 2008 at 04:38 PM 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? Link to comment Share on other sites More sharing options...
Knitter Posted June 26, 2008 at 04:52 PM Report Share #193738 Posted June 26, 2008 at 04:52 PM 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. www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Guest id194 Posted June 26, 2008 at 04:56 PM Report Share #193748 Posted June 26, 2008 at 04:56 PM Não querem dar um exemplo mais concreto de como se faria isso? Também vou precisar disto 👍 mas não estou a ver bem como faria, ainda não domino bem o comparator... Link to comment Share on other sites More sharing options...
Knitter Posted June 26, 2008 at 05:15 PM Report Share #193757 Posted June 26, 2008 at 05:15 PM 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(); } } www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Baderous Posted June 27, 2008 at 05:14 PM Author Report Share #194143 Posted June 27, 2008 at 05:14 PM 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; } Link to comment Share on other sites More sharing options...
Knitter Posted June 29, 2008 at 03:17 PM Report Share #194386 Posted June 29, 2008 at 03:17 PM Bem, dado que me parece já teres o problema resolvido não há muito mais a dizer 😉 www.sergiolopes.eu Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now