Collezione di oggetti

di il
38 risposte

Collezione di oggetti

È normale che per implementare questo programma
https://github.com/myblacksloth/javaPrograms/blob/master/HotelManagemet-SearchFilters/README.md
mi è stato detto di creare la collezione delle stanze all'interno dell'oggetto Hotel?
In modo tale che il gestore della collezione implementa una lista di Hotel e che ogni oggetto Hotel contiene un arrayList di stanze?

Insomma ne verrebbe fuori una cosa del genere

package com_antomau_HotelManagement.Classi;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Scanner;

public class Hotel {	
	
	
	private String serial, name, address,city, country, phone, fax;
	
	private ArrayList<Room> a; //collezione di stanze all'interno dell'oggetto Hotel
	
	
	
	public Hotel(String serial, String name, String address, String city, String country, String phone, String fax) //costruttore
	{
		this.serial = serial;
		this.name = name;
		this.address = address;
		this.city = city;
		this.country = country;
		this.phone = phone;
		this.fax = fax;
		this.a = new ArrayList<Room>(); //inizializzazione dell'arrayList di stanze
	}
	
	
	public void addRoom(Room r)
	{
		a.add(r);
	}
	
	public ArrayList<Room> getRooms()
	{
		return a;
	}
	
	public String getSerial()
	{
		return this.serial;
	}
	
	public String getName()
	{
		return this.name;
	}
	
	public String getAddress()
	{
		return this.address;
	}
	
	public String getCity()
	{
		return this.city;
	}
	
	public String getCountry()
	{
		return this.country;
	}
	
	public String getPhone()
	{
		return this.phone;
	}
	
	public String getFax()
	{
		return this.fax;
	}
	
	public void setSerial (String s)
	{
		this.serial = s;
	}
	
	public void setName (String s)
	{
		this.name = s;
	}
	
	public void setAddress (String s)
	{
		this.address = s;
	}
	
	public void setCity (String s)
	{
		this.city = s;
	}
	
	public void setCountry (String s)
	{
		this.country = s;
	}
	
	public void setPhone (String s)
	{
		this.phone = s;
	}
	
	public void setFax (String s)
	{
		this.fax = s;
	}
	
	public String toString()
	{
		return "Hotel: [" + serial + ", " + name + ", " + address + ", " + city + "," + country + ", " + phone + ", " + fax + "]";
	}
	
	public static Hotel read(Scanner sc)
	{
		assert sc.hasNext()==true;
		String serial = sc.nextLine();
		
		assert sc.hasNext()==true;
		String name = sc.nextLine();
		
		assert sc.hasNext()==true;
		String address = sc.nextLine();
		
		assert sc.hasNext()==true;
		String city = sc.nextLine();
		
		assert sc.hasNext()==true;
		String country = sc.nextLine();
		
		assert sc.hasNext()==true;
		String phone = sc.nextLine();
		
		assert sc.hasNext()==true;
		String fax = sc.nextLine();
		
		return new Hotel(serial, name, address, city, country, phone, fax);
		
	}





	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((address == null) ? 0 : address.hashCode());
		result = prime * result + ((city == null) ? 0 : city.hashCode());
		result = prime * result + ((country == null) ? 0 : country.hashCode());
		result = prime * result + ((fax == null) ? 0 : fax.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((phone == null) ? 0 : phone.hashCode());
		result = prime * result + ((serial == null) ? 0 : serial.hashCode());
		return result;
	}





	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Hotel other = (Hotel) obj;
		if (address == null) {
			if (other.address != null)
				return false;
		} else if (!address.equals(other.address))
			return false;
		if (city == null) {
			if (other.city != null)
				return false;
		} else if (!city.equals(other.city))
			return false;
		if (country == null) {
			if (other.country != null)
				return false;
		} else if (!country.equals(other.country))
			return false;
		if (fax == null) {
			if (other.fax != null)
				return false;
		} else if (!fax.equals(other.fax))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (phone == null) {
			if (other.phone != null)
				return false;
		} else if (!phone.equals(other.phone))
			return false;
		if (serial == null) {
			if (other.serial != null)
				return false;
		} else if (!serial.equals(other.serial))
			return false;
		return true;
	}
	
	
	public void print(PrintStream p)
	{
		p.println(serial);
		p.println(name);
		p.println(address);
		p.println(city);
		p.println(country);
		p.println(phone);
		p.println(fax);
	}
	
	
	
}

38 Risposte

  • Re: Collezione di oggetti

    antomau96 ha scritto:


    che ogni oggetto Hotel contiene un arrayList di stanze?
    Di per sé non c'è nulla di strano, è sensato.

    Il equals è un po' prolisso ma probabilmente l'hai fatto generare e il IDE lo "sa" generare solo così. Se ci sono svariati campi, personalmente invece che catene di if su if, tendo ad usare il nuovo equals di java.util.Objects (Java 7+) per gli oggetti oppure in generale e ancora meglio la classe EqualsBuilder della libreria Apache Commons Lang.

    Quello che è decisamente brutto e meno pulito è quel static Hotel read(Scanner sc), che inserisce in Hotel un concetto di I/O verso l'utente che non dovrebbe c'entrare nulla con Hotel. Se l'input fosse fatto in altro modo, che fai? Un altro readXyz() ? E se ne avessi un terzo formato? Un altro metodo read ? No così non va.
    Poi l'uso di quei assert è assolutamente sbagliato e inappropriato.
  • Re: Collezione di oggetti

    Ecco che qui casca l'asino!
    Quel metodo read fosse stato per me non lo avrei neanche implementato ma mi è stato chiesto esplicitamente dalla prof di implementarlo in quel modo......
    Invece di usare gli assert posso utilizzare
    
    if (!sc.hasNextLine())
    	return null;
    
    per ogni input?
    Purtroppo il read() lo devo implementare in quel modo per cause di forza maggiore
    Ma la cosa strana è che metodi simili non li sono riusciti a reperire da nessuna parte... Sto consultando 3 libri diversi e nessuno lo riporta
  • Re: Collezione di oggetti

    antomau96 ha scritto:


    
    if (!sc.hasNextLine())
    	return null;
    
    per ogni input?
    Dipende, si può vedere la questione in diversi modi. Se alla richiesta del primo dato manca l'input, si potrebbe intendere "fine dei record" e quindi restituire null (il chiamante farà ipoteticamente un ciclo "finché ci sono hotel", ovvero fintanto che read restituisce diverso da null).
    Se alle richieste successive manca l'input, si può intendere che l'input è "malformato" e quindi lanciare una eccezione. Se lo Scanner fosse verso un file, il senso è generalmente proprio quello: finché ci sono record completi, ok. Se un record è parziale dipende come vuoi trattarlo ma la cosa più semplice e ovvia è trattarlo come un "errore".

    antomau96 ha scritto:


    Purtroppo il read() lo devo implementare in quel modo per cause di forza maggiore
    Se proprio "devi", implementalo. Chiudiamo qualche occhio .....
  • Re: Collezione di oggetti

    Dovendo quindi usare il metodo read() sia di Hotel che di Room devo creare un metodo, chiamato dal costruttore della classe, che verifica la presenza dei dati all'interno del file e chiama ad oltranza il metodo read per creare la collezione?
    Mi spiego meglio
    nella classe Hotel creo un metodo che carica le stanze
    trovo nel file l'elenco di stanze corrispondenti all'hotel
    questo implementa uno scanner
    fintanto che lo scanner ha una nuova linea
    chiama il metodo read della stanza e caricala nell'array di stanze

    il tutto viene invocato dal gestore della collezione che prende così l'hotel ottenuto e lo inserisce nella lista...
    ovviamente il gestore della collezione deve a sua volta implementare un metodo simile per caricare gli hotel, ed è proprio questo metodo che richiama il procedimento sopra descritto....

    è questa la struttura che devo utilizzare per questo programma?
  • Re: Collezione di oggetti

    Up
    Si può strutturare in questo modo il programma?
  • Re: Collezione di oggetti

    antomau96 ha scritto:


    Up
    Si può strutturare in questo modo il programma?
    Ascolta: se ho ben capito il "codice albergo" è la chiave che lega i dati tra i file alberghi.dat e stanze.dat. Quindi: leggi tutto il alberghi.dat e metti tutti gli oggetti Hotel in una lista. Siccome però gli alberghi è utile "indicizzarli" per quel codice, metti anche una mappa che associa codice->oggetto Hotel.
    Poi leggi tutto stanze.dat, per ciascuna stanza hai il codice albergo e con questo vai a ripescare velocemente l'oggetto Hotel. Quindi una volta ottenuto l'oggetto Room, lo aggiungi nel Hotel.

    È questo che intendi??
  • Re: Collezione di oggetti

    Si intendo questo...
    L'unica cosa è che la mappa non la uso perché la richiesta che mi è stata avanzata è stata di creare un arrayList di stanze nell'oggetto albergo e anche se io non sono proprio d'accordo con questa prassi purtroppo sono obligato a doverla metterla in pratica...

    Ritornando ad una vecchia questione, credo di aver capito finalmente cosa è un filtro di ricerca e in che modo questo debba essere implementato... almeno spero... va bene questa implementazione
    
    public List findPrice(int p)
    	{
    		List f = new List();
    	 
    		ListIterator li = l.listIterator();
    		while (li.hasNext())
    		{
    			Hotel h = li.next();
    			ArrayList<Room> rr = h.getRooms();
    			boolean found = false;
    			ArrayList<Room> alr = new ArrayList<Room>();
    			for (Room r : rr)
    			{
    				if (r.getPrice() <= p)
    				{
    					found = true;
    					alr.add(r);
    				}
    			}
    			if (found)
    			{
    				Hotel hotelResult = new Hotel(h.getSerial(), h.getName(), h.getAddress(), h.getCity(), h.getCountry(), h.getPhone(), h.getFax());
    				hotelResult.setRooms(alr);
    				f.addFirst(hotelResult);
    			}
    		}
    		
    		return f;
    	}
    
    Adesso avrò un filtro di ricerca per ogni singola caratteristica che si vuole cercare il quale restituisce un oggetto dello stesso tipo della collezione (in questo caso la collezione è una lista di stanze e quindi esso restituirà una lista di stanze)

    Se per chiarezza devo postare il codice completo del programma non ci sono problemi

    Quello che vorrei fare è ordinare l'arrayList in modo da poter implementare la ricerca binaria almeno per il prezzo...
  • Re: Collezione di oggetti

    antomau96 ha scritto:


    L'unica cosa è che la mappa non la uso perché la richiesta che mi è stata avanzata è stata di creare un arrayList di stanze nell'oggetto albergo e anche se io non sono proprio d'accordo con questa prassi purtroppo sono obligato a doverla metterla in pratica...
    La mappa codice->Hotel ovviamente NON è fondamentale. Se non la usi, hai solo da fare una ricerca "lineare" del codice (ovviamente è meno efficiente).
    E comunque se usassi una mappa non sei obbligato a tenerla per sempre anche nel resto della applicazione, potresti tenerla anche solo temporaneamente nella logica di caricamento, giusto il tempo necessario per "legare" le room agli hotel.

    antomau96 ha scritto:


    credo di aver capito finalmente cosa è un filtro di ricerca
    Un filtro di ricerca è un "predicato" (booleano) che dice semplicemente se considerare un elemento oppure no in base a "certi criteri". Stop, concettualmente è tutto qui.

    antomau96 ha scritto:


    public List findPrice(int p)
    Adesso avrò un filtro di ricerca per ogni singola caratteristica che si vuole cercare
    Quindi oltre a findPrice avrai un es. findCity, findXYZ ecc...? E ciascuno ha la logica REPLICATA per scansionare Hotel/Room?
    E se invochi più findXXX ed essi ti danno appunto ciascuno una nuova lista .... cosa te ne fai?

    Dai ... è Venerdì 17 ... stiamo scherzando, giusto?
  • Re: Collezione di oggetti

    Infatti era proprio quello che volevo chiederti sul da farsi per applicare filtri multipli perché quello che è stato detto è:
    ogni filtro restituisce la collezione
    per applicare più filtri si filtrano i risultati di un filtro con un nuovo filtro...
    teoricamente la cosa è comprensibile e di facile immaginazione ma il problema sarebbe proprio andare ad applicare un qualcosa del genere...

    Altra cosa che mi è stato detto è che il filtro non restituisce true/false ma la collezione...

    Se vuoi, ho un esempio di programma (molto diverso da questo) svolto in questo modo in aula, per capire di cosa sto parando...

    Tu cosa mi consigli di fare per la ricerca? (visto che il metodo che avevo usato l'altra volta, seppur funzionante, era barbaramente scorretto )

    p.s.: i filtri così funzionano bene ma sono praticamente 5 metodi la cui differenza sta solo nelle condizioni di un if... e che restituiscono ognuno una collezione indipendente...
    Find by price 54:
    Hotel: [testh, hotel, via del test, 123, citta, paese, 320320, 321321]
    	Room [type=2, num=12, price=46, tv=true, air=true, fridge=true, internet=false]
    Hotel: [hotelfxxk, hotelKK, via del pappagallo, 122, roma, italia, 320321, 320322]
    	Room [type=3, num=44, price=33, tv=false, air=false, fridge=false, internet=false]
    
    Find by tv:
    Hotel: [testh, hotel, via del test, 123, citta, paese, 320320, 321321]
    	Room [type=1, num=23, price=56, tv=true, air=true, fridge=true, internet=true]
    	Room [type=2, num=12, price=46, tv=true, air=true, fridge=true, internet=false]
    Hotel: [hotelfxxk, hotelKK, via del pappagallo, 122, roma, italia, 320321, 320322]
    	Room [type=1, num=22, price=99, tv=true, air=true, fridge=true, internet=true]
    	Room [type=2, num=33, price=55, tv=true, air=false, fridge=false, internet=false]
    
    Find by air:
    Hotel: [testh, hotel, via del test, 123, citta, paese, 320320, 321321]
    	Room [type=1, num=23, price=56, tv=true, air=true, fridge=true, internet=true]
    	Room [type=2, num=12, price=46, tv=true, air=true, fridge=true, internet=false]
    Hotel: [hotelfxxk, hotelKK, via del pappagallo, 122, roma, italia, 320321, 320322]
    	Room [type=1, num=22, price=99, tv=true, air=true, fridge=true, internet=true]
    
    Find by fridge:
    Hotel: [testh, hotel, via del test, 123, citta, paese, 320320, 321321]
    	Room [type=1, num=23, price=56, tv=true, air=true, fridge=true, internet=true]
    	Room [type=2, num=12, price=46, tv=true, air=true, fridge=true, internet=false]
    Hotel: [hotelfxxk, hotelKK, via del pappagallo, 122, roma, italia, 320321, 320322]
    	Room [type=1, num=22, price=99, tv=true, air=true, fridge=true, internet=true]
    
    Find by internet:
    Hotel: [testh, hotel, via del test, 123, citta, paese, 320320, 321321]
    	Room [type=1, num=23, price=56, tv=true, air=true, fridge=true, internet=true]
    Hotel: [hotelfxxk, hotelKK, via del pappagallo, 122, roma, italia, 320321, 320322]
    	Room [type=1, num=22, price=99, tv=true, air=true, fridge=true, internet=true]
  • Re: Collezione di oggetti

    antomau96 ha scritto:


    per applicare più filtri si filtrano i risultati di un filtro con un nuovo filtro...
    Se è così ha senso e di per sé tecnicamente funziona. Ma è comunque una soluzione per niente buona e ottimale: ripeti le scansioni delle strutture più volte ed è comunque un gran spreco di risorse, in generale ma anche per il fatto che fai COPIE degli Hotel.

    antomau96 ha scritto:


    Altra cosa che mi è stato detto è che il filtro non restituisce true/false ma la collezione...
    Una cosa è un metodo che applica una qualche logica di filtro es. da una lista di N elementi tira fuori una lista di M elementi (M <= N) e un'altra cosa è il "predicato" booleano del filtro, che si può realizzare in vari modi.
    Sono due cose diverse ... non ti è ancora chiaro?

    antomau96 ha scritto:


    Tu cosa mi consigli di fare per la ricerca?
    Ascolta, l'avevo già detto di recente sicuramente. Ci sono 2 concetti ben distinti:

    a) Il concetto di COME iterare sulla/e struttura/e dati a disposizione.
    b) Il concetto di COME stabilire se un elemento deve essere incluso o escluso.

    Il modo di implementazione di tutto questo dipende principalmente da un fattore: QUANTO vuoi separare questi due concetti.

    Se li vuoi separare tanto e bene (e rendendo oltretutto la logica del punto a) facilmente riutilizzabile), allora si fa tipicamente una interface di astrazione del "predicato" e quindi il metodo di filtro riceve questo predicato sotto forma di un oggetto che ha il "comportamento" (la logica) per dire se accettare un elemento o no.

    Puoi trovare strade intermedie fino ad arrivare al caso opposto estremo in cui le logiche a) e b) sono tutte ammassate e annegate insieme nello stesso metodo.
  • Re: Collezione di oggetti

    Al momento non mi interessa particolarmente separare le due cose... Mi basterebbe solo fare in modo da ottenere una nuova collezione contenente i dati cercati ma non mi è ben chiaro come collegare tra loro i "filtri" (metodi per la ricerca) perché l'unica cosa che mi viene in mente è creare dei metodi che accettano come parametro la lista in cui cercare... ma non credo che sia questo il modo migliore per implementare una ricerca...

    Mi servirebbe proprio uno spunto sul da farsi per poter sfruttare più "filtri" contemporaneamente
  • Re: Collezione di oggetti

    antomau96 ha scritto:


    Mi basterebbe solo fare in modo da ottenere una nuova collezione contenente i dati cercati ma non mi è ben chiaro come collegare tra loro i "filtri"
    Non è che puoi "collegare" più metodi .... non così come stavi facendo che è comunque assurdo/inefficiente.
    Senza andare a fare design particolari a livello object-oriented, quello che puoi fare è passare ad 1 metodo di filtro TUTTI i dati per i fitri.

    Scenario 1)
    public List<Hotel> findRooms(Integer minPrice, Integer maxPrice, Boolean airConditioned) {
        List<Hotel> result = .......
    
        // iterazione/i
        {
            if ( ...usa TUTTI i dati di filtro... ) {
                // aggiungi in result
            }
        }
    
        return result;
    }
    Ho usato dati Integer/Boolean così un eventuale null potrebbe essere usato per dire "non applicare questo filtro".


    Scenario 2)

    Se hai tanti dati e/o pensi di aggiungerne di più in futuro, puoi anche raggruppare tutti i dati di filtro in una apposita classe.
    public class RoomFilterData {
        private Integer minPrice;
        private Integer maxPrice;
        private Boolean airConditioned;
    
        // (costruttore), getter, setter, etc...
    }
    e poi findRooms diventa semplicemente:

    public List<Hotel> findRooms(RoomFilterData filterData) { ........ }

    Ma il succo non cambia .... senza cercare design particolari alla fin fine è TUTTO QUI.
  • Re: Collezione di oggetti

    Scusami Andrea,
    sto facendo il programma con i filtri che mi restituiscono true e false ma non mi è chiara questa cosa:
    ho il gestore dei fitltri

    andbin ha scritto:


    Scenario 1)
    che scorre la collezione e quando trova una stanza la passa al filtro di ricerca
    che quindi accetta come parametro la stanza
    e restituisce true/false in base alla presenza o meno di quella caratteristica?

    Ho capito bene come il tutto va implementato?
    public boolean findMinusPrice(Room r, int p)
    	{
    		if (r.getPrice() <= p) return true;	
    		
    		return false;
    	}
    Per intenderci una cosa del genere...?

    E questo sarebbe il gestore dei filtri di ricerca (Ancora incompleto)
    
    	public List roomFilter(int price)
    	{
    		List results = new List();
    		
    		ListIterator li = l.listIterator();
    		
    		while (li.hasNext())
    		{
    			Hotel h = li.next(); //hotel presente nella lista
    			
    			ArrayList<Room> rr = h.getRooms(); //arrayList del corrente hotel presente nella lista
    			
    			ArrayList<Room> filteredRooms = new ArrayList<Room>(); //arrayList di stanze filtrate
    			
    			for (Room r : rr)
    			{
    				//devo aggiungere un controllo sulle varie cose che voglio filtrare! non voglio applicare obligatoriamente tutti i filtri!
    				if (findMinusPrice(r, price))
    				{
    					filteredRooms.add(r);
    				}
    			}
    			
    			h.setRooms(filteredRooms);
    			results.addFirst(h);
    		}
    		
    		return results;
    	}
    
  • Re: Collezione di oggetti

    antomau96 ha scritto:


    Ho capito bene come il tutto va implementato?
    Scusa ma quale è la difficoltà o dubbio nel fare qualcosa tipo esempio:

    public List<Hotel> findRooms(Integer minPrice, Integer maxPrice, Boolean airConditioned, ......tutti gli altri dati che ti pare........)

    OPPURE

    public List<Hotel> findRooms(RoomFilterData filterData)

    ?
Devi accedere o registrarti per scrivere nel forum
38 risposte