View Full Version : classe scanner per leggere da file
stregone_giallo_rosso
03-07-2007, 11:28
Salve ho un file di questo tipo:
costruttore
modello
versione
anno
***accessori***
vetri
fari
____
_____
***accessori***
devo scrivere un metodo per leggere le linee dal file, il problema che le linee di accessori possono variere e non posso considerarla come un unica linea e quindi un met tipo getAcc(), come faccio a leggere solo le linee che sono nel file che possono variare
Devi avere un marcatore determinabile dai dati presenti nel file. Ad esempio nel testo del file che hai incollato si potrebbe dire che la prima linea contenente la stringa "***Accessori***" indichi la sezione del documento a partire dalla quale il lettore troverà gli accessori. L'elenco di accessori continua finchè il lettore non trovi una seconda linea contenente la stessa stringa.
La lettura degli accessori diventerebbe:
leggi il file linea per linea finchè non trovi la stringa "***Accessori***"
da qui in poi ogni linea rappresenta un accessorio a meno che non contenga di nuovo la stringa "***Accessori***". Se contiene la stringa "***Accessori***" allora non ci sono più accessori da leggere.
Il metodo getAccessory() potrebbe quindi essere:
se non esistono più accessori {
return null o throw exception.
}
se non l'hai già fatto {
cerca la prima linea che contiene la stringa ***Accessori***
}
String nome = leggiLinea();
se nome contiene ***Accessori*** non esistono più accessori, nome = null;
return nome;
stregone_giallo_rosso
03-07-2007, 12:39
ok, ma poi come faccio a leggerle dal file insieme :
public static Auto read (Scanner in){
if(!hasNext()) return null;
return new Auto (cost,mod,vers,anno,???)
mi puoi scrivere il codice
Posso scriverti UN codice. IL codice potrebbe essere diverso.
Supponendo che questo sia il file di testo che contiene le informazioni da tradurre in un'Automobile:
fiat
punto
base
2006
***accessori***
vetri
volante
pedali
sedili
***accessori***
La lettura potrebbe essere:
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) {
File inputFile = new File(args[0]);
Auto auto = null;
try {
auto = new Auto(new LettoreDatiAutomobile().leggiDati(inputFile));
} catch(IOException ex) {
System.err.println("Errore durante la lettura del file " + inputFile);
}
if(auto != null) {
System.out.println("Costruttore: " + auto.getCostruttore());
System.out.println("Modello: " + auto.getModello());
System.out.println("Versione: " + auto.getVersione());
System.out.println("Anno: " + auto.getAnno());
System.out.println("Lista Accessori:");
for(String s : auto.getAccessori()) {
System.out.println("\t" + s);
}
}
}
}
/** Questo oggetto traduce le informazioni contenute in un file di testo in
un pacchetto di dati per l'inizializzazione di un'auto */
class LettoreDatiAutomobile {
private final String MARCATORE_ACCESSORI = "***accessori***";
public DatiInizializzazioneAuto leggiDati(File file) throws IOException {
DatiInizializzazioneAuto dati = new DatiInizializzazioneAuto();
Scanner scanner = null;
/* tenta di leggere */
try {
scanner = new Scanner(file);
/* legge le prime quattro righe */
caricaIntestazione(scanner, dati);
/* legge il resto se presente e corrispondente ad un elenco
di accessori */
caricaAccessori(scanner, dati);
} finally {
/* cascasse il mondo, se lo scanner è stato aperto allora sarà
anche chiuso */
if(scanner != null) {
scanner.close();
}
}
return dati;
}
private void caricaIntestazione(Scanner input, DatiInizializzazioneAuto dati) throws IOException {
dati.setCostruttore(input.nextLine());
dati.setModello(input.nextLine());
dati.setVersione(input.nextLine());
dati.setAnno(input.nextLine());
}
private void caricaAccessori(Scanner input, DatiInizializzazioneAuto dati) throws IOException {
/* Se la linea corrente vale ***accessori*** */
if(input.hasNextLine() && input.nextLine().equals(MARCATORE_ACCESSORI)) {
/* per ogni linea successiva */
while(input.hasNextLine()) {
String linea = input.nextLine();
/* se quella linea vale ***accessori*** esce dal ciclo di lettura */
if(linea.equals(MARCATORE_ACCESSORI)) {
break;
} else {
/* altrimenti carica quella linea nei dati come accessorio */
dati.aggiungiAccessorio(linea);
}
}
}
}
}
/** Pacchetto di dati usato per l'inizializzazione di un Auto. */
class DatiInizializzazioneAuto {
private String costruttore;
private String modello;
private String versione;
private String anno;
private LinkedList<String> accessori = new LinkedList<String>();
public void setCostruttore(String costruttore) {
this.costruttore = costruttore;
}
public String getCostruttore() {
return costruttore;
}
public void setModello(String modello) {
this.modello = modello;
}
public String getModello() {
return modello;
}
public void setVersione(String versione) {
this.versione = versione;
}
public String getVersione() {
return versione;
}
public void setAnno(String anno) {
this.anno = anno;
}
public String getAnno() {
return anno;
}
public void aggiungiAccessorio(String accessorio) {
accessori.add(accessorio);
}
public Collection<String> getAccessori() {
return accessori;
}
}
/** Questa classe rappresenta un'automobile. */
class Auto {
private String costruttore;
private String modello;
private String versione;
private String anno;
private ArrayList<String> accessori;
/** Le istanze di Auto sono inizializzate usando un pacchetto di informazioni
di tipo DatiInitializzazioneAuto. */
public Auto(DatiInizializzazioneAuto dati) {
costruttore = dati.getCostruttore();
modello = dati.getModello();
versione = dati.getVersione();
anno = dati.getAnno();
accessori = new ArrayList<String>(dati.getAccessori());
}
public String getCostruttore() {
return costruttore;
}
public String getModello() {
return modello;
}
public String getVersione() {
return versione;
}
public String getAnno() {
return anno;
}
public Collection<String> getAccessori() {
return accessori;
}
}
Il procedimento usato è il seguente.
Si crea un DatiInizializzazioneAuto. Ai apre il file e si legge linea per linea. Per ogni linea, in base ad una convenzione implicita di formato, si immette nel DatiInizializzazioneAuto il corrispondente valore. Ad esempio la prima riga è il nome del costruttore, dunque lo leggo e lo passo al DatiInizializzazioneAuto usando il suo metodo setCostruttore(String).
Una volta completata la lettura del file, il pacchetto di informazioni, costruito in modo incrementale, cioè un pezzo alla volta, viene usato per la costruzione di un oggetto Auto.
Tutto qui.
stregone_giallo_rosso
03-07-2007, 16:08
Grazie! sei un grande!!!!
Ci sentiamo presto.
stregone_giallo_rosso
04-07-2007, 14:54
scuasami riusciresti a farlo con in interfaccia grafica
Una tra il miliardo di possibili rappresentazioni è quella contenuta qui di seguito.
Come prima, si tratta di un'unica unità di compilazione, di nome Main.java. Significa che se copi tutto quanto in un file di nome Main.java, compili ed esegui puoi provare il programma. Lo faccio per brevità: non è una buona idea in generale.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.beans.*;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() { public void run() {
new InterfacciaGrafica().show();
}});
}
}
/** Dichiarazione delle capacità di un elemento dell'interfaccia grafica.
Serve per "mettere in comunicazione" i vari pezzi. */
interface ElementoInterfacciaGrafica {
void setInterfacciaGrafica(InterfacciaGrafica ig);
}
/** Gestisce la finestra principale del programma e permette ai diversi
elementi di dialogare tra loro. */
class InterfacciaGrafica {
private JFrame finestra = new JFrame("Auto");
private PannelloAutomobile pannelloAutomobile = new PannelloAutomobile();
private BarraDeiComandi barraDeiComandi = new BarraDeiComandi();
public PannelloAutomobile getPannelloAutomobile() {
return pannelloAutomobile;
}
public BarraDeiComandi getBarraDeiComandi() {
return barraDeiComandi;
}
public void setComponent(Component c, Object constraints) {
finestra.add(c, constraints);
}
public void show() {
if(finestra.isVisible() == false) {
pannelloAutomobile.setInterfacciaGrafica(this);
barraDeiComandi.setInterfacciaGrafica(this);
finestra.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
finestra.pack();
finestra.setVisible(true);
}
}
}
/** Visualizza e gestisce i pulsanti dell'interfaccia (quelli in alto) */
class BarraDeiComandi implements ElementoInterfacciaGrafica {
private InterfacciaGrafica interfacciaGrafica;
private JFileChooser fileChooser = new JFileChooser();
private JButton pulsanteCaricaDati = new JButton("Carica dati");
private JPanel contenitore = new JPanel(new FlowLayout(FlowLayout.LEFT));
public BarraDeiComandi() {
contenitore.add(pulsanteCaricaDati);
pulsanteCaricaDati.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
scegliFile();
}
});
}
public void setInterfacciaGrafica(InterfacciaGrafica g) {
interfacciaGrafica = g;
interfacciaGrafica.setComponent(contenitore, BorderLayout.NORTH);
}
private void scegliFile() {
Component parent = JOptionPane.getFrameForComponent(contenitore);
int risposta = fileChooser.showOpenDialog(parent);
if(risposta == JFileChooser.APPROVE_OPTION) {
File fileScelto = fileChooser.getSelectedFile();
if(fileScelto != null && fileScelto.canRead() && fileScelto.exists()) {
caricaDati(fileScelto);
} else {
JOptionPane.showMessageDialog(
parent,
"Il file scelto non esiste o non può essere letto");
}
}
}
private void caricaDati(File file) {
try {
DatiInizializzazioneAuto dati = new LettoreDatiAutomobile().leggiDati(file);
Auto auto = new Auto(dati);
interfacciaGrafica.getPannelloAutomobile().setAuto(auto);
} catch(Exception ex) {
Component parent = JOptionPane.getFrameForComponent(contenitore);
JOptionPane.showMessageDialog(parent,
"Errore durante il caricamento dei dati.");
ex.printStackTrace();
}
}
}
/** Pannello che presenta i dati di un'automobile */
class PannelloAutomobile implements ElementoInterfacciaGrafica {
private InterfacciaGrafica interfacciaGrafica;
private JTextField campoCostruttore = new JTextField(10);
private JTextField campoModello = new JTextField(10);
private JTextField campoVersione = new JTextField(10);
private JTextField campoAnno = new JTextField(10);
private DefaultListModel modelloListaAccessori = new DefaultListModel();
private JList listaAccessori = new JList(modelloListaAccessori);
private JScrollPane contenitoreListaAccessori = new JScrollPane(listaAccessori);
private Auto auto;
private JPanel pannello = new JPanel(new GridBagLayout());
public PannelloAutomobile() {
JLabel etichettaIntestazione = new JLabel("Dati auto");
JLabel etichettaCostruttore = new JLabel("Costruttore");
JLabel etichettaModello = new JLabel("Modello");
JLabel etichettaVersione = new JLabel("Versione");
JLabel etichettaAnno = new JLabel("Anno");
JLabel etichettaAccessori = new JLabel("Accessori");
GridBagConstraints lim = new GridBagConstraints();
lim.insets = new Insets(4, 4, 4, 4);
lim.weightx = 0;
lim.gridx = 0;
lim.gridy = 0;
lim.gridwidth = 2;
lim.fill = GridBagConstraints.NONE;
pannello.add(etichettaIntestazione, lim);
lim.fill = GridBagConstraints.HORIZONTAL;
lim.weightx = 0;
lim.gridx = 0;
lim.gridy = 1;
lim.gridwidth = 1;
pannello.add(etichettaCostruttore, lim);
lim.weightx = 1;
lim.gridx = 1;
lim.gridy = 1;
pannello.add(campoCostruttore, lim);
lim.weightx = 0;
lim.gridx = 0;
lim.gridy = 2;
pannello.add(etichettaModello, lim);
lim.gridx = 1;
lim.gridy = 2;
pannello.add(campoModello, lim);
lim.gridx = 0;
lim.gridy = 3;
pannello.add(etichettaVersione, lim);
lim.gridx = 1;
lim.gridy = 3;
pannello.add(campoVersione, lim);
lim.gridx = 0;
lim.gridy = 4;
pannello.add(etichettaAnno, lim);
lim.gridx = 1;
lim.gridy = 4;
pannello.add(campoAnno, lim);
lim.gridx = 0;
lim.gridy = 5;
lim.gridwidth = 2;
lim.fill = GridBagConstraints.NONE;
pannello.add(etichettaAccessori, lim);
lim.gridx = 0;
lim.gridy = 6;
lim.weighty = 1;
lim.gridwidth = 2;
lim.fill = GridBagConstraints.BOTH;
pannello.add(contenitoreListaAccessori, lim);
pannello.setBorder(BorderFactory.createEtchedBorder());
pannello.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
if(e.getPropertyName().equals("ancestor")) {
congelaLarghezzaCampiDiTesto();
}
}
});
}
private void congelaLarghezzaCampiDiTesto() {
setSizeFor(campoCostruttore, campoCostruttore.getPreferredSize());
setSizeFor(campoModello, campoModello.getPreferredSize());
setSizeFor(campoVersione, campoVersione.getPreferredSize());
setSizeFor(campoAnno, campoAnno.getPreferredSize());
}
private void setSizeFor(Component c, Dimension size) {
c.setMinimumSize(size);
c.setMaximumSize(size);
c.setPreferredSize(size);
}
public void setInterfacciaGrafica(InterfacciaGrafica g) {
interfacciaGrafica = g;
interfacciaGrafica.setComponent(pannello, BorderLayout.CENTER);
}
public void setAuto(Auto auto) {
this.auto = auto;
acquisisciDati();
}
private void azzeraCampi() {
campoCostruttore.setText("");
campoModello.setText("");
campoVersione.setText("");
campoAnno.setText("");
modelloListaAccessori.clear();
}
private void acquisisciDati() {
if(auto == null) {
azzeraCampi();
} else {
campoCostruttore.setText(auto.getCostruttore());
campoModello.setText(auto.getModello());
campoVersione.setText(auto.getVersione());
campoAnno.setText(auto.getAnno());
modelloListaAccessori.clear();
for(String accessorio : auto.getAccessori()) {
modelloListaAccessori.addElement(accessorio);
}
}
}
}
/** Questo oggetto traduce le informazioni contenute in un file di testo in
un pacchetto di dati per l'inizializzazione di un'auto */
class LettoreDatiAutomobile {
private final String MARCATORE_ACCESSORI = "***accessori***";
public DatiInizializzazioneAuto leggiDati(File file) throws IOException {
DatiInizializzazioneAuto dati = new DatiInizializzazioneAuto();
Scanner scanner = null;
/* tenta di leggere */
try {
scanner = new Scanner(file);
/* legge le prime quattro righe */
caricaIntestazione(scanner, dati);
/* legge il resto se presente e corrispondente ad un elenco
di accessori */
caricaAccessori(scanner, dati);
} finally {
/* cascasse il mondo, se lo scanner è stato aperto allora sarà
anche chiuso */
if(scanner != null) {
scanner.close();
}
}
return dati;
}
private void caricaIntestazione(Scanner input, DatiInizializzazioneAuto dati) throws IOException {
dati.setCostruttore(input.nextLine());
dati.setModello(input.nextLine());
dati.setVersione(input.nextLine());
dati.setAnno(input.nextLine());
}
private void caricaAccessori(Scanner input, DatiInizializzazioneAuto dati) throws IOException {
/* Se la linea corrente vale ***accessori*** */
if(input.hasNextLine() && input.nextLine().equals(MARCATORE_ACCESSORI)) {
/* per ogni linea successiva */
while(input.hasNextLine()) {
String linea = input.nextLine();
/* se quella linea vale ***accessori*** esce dal ciclo di lettura */
if(linea.equals(MARCATORE_ACCESSORI)) {
break;
} else {
/* altrimenti carica quella linea nei dati come accessorio */
dati.aggiungiAccessorio(linea);
}
}
}
}
}
/** Pacchetto di dati usato per l'inizializzazione di un Auto. */
class DatiInizializzazioneAuto {
private String costruttore;
private String modello;
private String versione;
private String anno;
private LinkedList<String> accessori = new LinkedList<String>();
public void setCostruttore(String costruttore) {
this.costruttore = costruttore;
}
public String getCostruttore() {
return costruttore;
}
public void setModello(String modello) {
this.modello = modello;
}
public String getModello() {
return modello;
}
public void setVersione(String versione) {
this.versione = versione;
}
public String getVersione() {
return versione;
}
public void setAnno(String anno) {
this.anno = anno;
}
public String getAnno() {
return anno;
}
public void aggiungiAccessorio(String accessorio) {
accessori.add(accessorio);
}
public Collection<String> getAccessori() {
return accessori;
}
}
/** Questa classe rappresenta un'automobile. */
class Auto {
private String costruttore;
private String modello;
private String versione;
private String anno;
private ArrayList<String> accessori;
/** Le istanze di Auto sono inizializzate usando un pacchetto di informazioni
di tipo DatiInitializzazioneAuto. */
public Auto(DatiInizializzazioneAuto dati) {
costruttore = dati.getCostruttore();
modello = dati.getModello();
versione = dati.getVersione();
anno = dati.getAnno();
accessori = new ArrayList<String>(dati.getAccessori());
}
public String getCostruttore() {
return costruttore;
}
public String getModello() {
return modello;
}
public String getVersione() {
return versione;
}
public String getAnno() {
return anno;
}
public Collection<String> getAccessori() {
return accessori;
}
}
C'è tutto il codice dell'altra volta, uguale, più quattro new entry.
ElementoInterfacciaGrafica
InterfacciaGrafica
BarraDeiComandi
PannelloAutomobile
Premendo il pulsante in alto si apre la finestra standard per la selezione di un file. Scegliendo un file che contiene i dati di un'automobile vengono riempiti i campi del pannello centrale.
stregone_giallo_rosso
04-07-2007, 21:16
ok grazie, scusami pero il programma mi kiede :
dato un costruttore restituire l'elenco dei modelli
selezionato uno dei modelli listati rest l'elenco delle auto
selezinata un auto mostri la scheda completa
sempre con l'interfaccia grafica
:D Mi sto divertendo come un "rigazzino" a farlo :D.
Quando finisco ti mando i sorgenti. O tutto il progetto, se usi NetBeans.
stregone_giallo_rosso
05-07-2007, 16:36
no uso eclipse, è per l'esame di programmazione all'uni!!!!!!!!
stregone_giallo_rosso
05-07-2007, 16:52
per evitare troppo codice getAccessori() lo potrei inserire nella classe auto nel metodo statico read:
public static Auto read (Scanner in){
if(!hasNext()) return null;
return new Auto (cost,mod,vers,anno,???)
in modo che dopo posso caricate gli oggetti Auto in un unico arraylist per fare il confronto dopo???
se è si puoi farmi un esempio perchè non riesco
thanks:)
no uso eclipse, è per l'esame di programmazione all'uni!!!!!!!!
Ah, ok. Niente codice.
La questione dell'array list dipende da come sono conservate le automobili nel file.
Se esistono N file, ognuno con una sola automobile è un paio di maniche.
Se un unico file contiene tutte le automobili, è un'altra camicia.
Nel secondo caso puoi sfruttare la progressività di Scanner. Puoi creare un oggetto DatiAutomobile che si inizializza usando uno Scanner. Una cosa dello pseudo-tipo:
class DatiInizializzazioneAuto {
public DatiInizializzazioneAuto(Scanner scanner) {
this.costruttore = scanner.nextLine();
this.modello = scanner.nextLine();
this.versione = scanner.nextLine();
this.anno = scanner.nextLine();
String linea;
scanner.nextLine(); //salta la prima linea ***accessori***
while(!(linea = scanner.nextLine()).equals("***accessori***")) {
listaAccessori.add(linea);
}
Con questa roba qui e uno Scanner aperto su un file nel formato già citato, la creazione dell'elenco di automobile diventa:
while(scanner.hasNextLine()) {
DatiInizializzazioneAuto dati = new DatiInizializzazioneAuto(scanner);
Auto auto = new Auto(dati);
listaAuto.add(auto); //listaAuto è un ArrayList<Auto>
}
Il codice sorgente del tuo programma deve essere una rappresentazione diretta e fedele del sistema che vuoi creare, per come tu l'hai inteso.
Evitare di scrivere troppo codice è l'assillo del programmatore-fruttivendolo. Qui non si vende un tanto al kilo: ci vogliono le linee che ci vogliono.
stregone_giallo_rosso
05-07-2007, 17:40
si è contenuto tutto in un unico file
stregone_giallo_rosso
05-07-2007, 17:47
ok grazie, scusami pero il programma mi kiede :
dato un costruttore restituire l'elenco dei modelli
selezionato uno dei modelli listati rest l'elenco delle auto
selezinata un auto mostri la scheda completa
sempre con l'interfaccia grafica
se non ti dispiace puoi scrivermi il codice , il file è uno, in cui sono contenute tutte le auto. (il mio metodo statico quindi non va bene???:confused: )
è per l'esame di programmazione all'uni!!!!!!!!
Non posso. Ma è facile, basta che metti insieme quelle due cose di cui abbiamo parlato.
stregone_giallo_rosso
05-07-2007, 20:17
é quello che non riesco a fare, ti prego aiutami... il metodo statico è giusto o no?
Non è una questione di cattiveria.
Io potrei anche dirti che il metodo statico non va bene perchè è statico. Ma le valutazioni che devi fare tu dipendono dal grado di preparazione che si presume tu abbia dopo aver seguito il corso di cui sosterrai l'esame.
Se non fosse statico, avresti comunque il problema della molteplicità di accessori.
La soluzione al caricamento di un numero indeterminato di accessori l'abbiamo vista. Non è che "DatiInizializzazioneAuto" io l'abbia messo perchè mi piace scrivere doppio :D Ha una particolarità che è quella di consentire la definizione incrementale (un po' alla volta) del proprio stato.
Non vedo questa capacità in Auto: un'automobile gli accessori ce li ha non ce li ha dall'inizio. Per questo separo l'inizializzazione "un po' per volta" usando un DatiInizializzazioneAuto per... inizializzare un'Auto.
Ma anche qui dovrei per onestà far notare che se tu porti un esercizio in cui mostri un caso di inizializzazione incrementale e il tuo prof ti dice: uh che bello, spiegamelo un po', che facciamo? Me lo passi al telefono? :D
stregone_giallo_rosso
06-07-2007, 01:23
lo so comprendo perfettamente, però almeno fammi vedere come si fa, perchè non riesco proprio,io cerco di capire quello che scrivi non lo copio soltanto
stregone_giallo_rosso
06-07-2007, 01:38
Ah, ok. Niente codice.
La questione dell'array list dipende da come sono conservate le automobili nel file.
Se esistono N file, ognuno con una sola automobile è un paio di maniche.
Se un unico file contiene tutte le automobili, è un'altra camicia.
Nel secondo caso puoi sfruttare la progressività di Scanner. Puoi creare un oggetto DatiAutomobile che si inizializza usando uno Scanner. Una cosa dello pseudo-tipo:
class DatiInizializzazioneAuto {
public DatiInizializzazioneAuto(Scanner scanner) {
this.costruttore = scanner.nextLine();
this.modello = scanner.nextLine();
this.versione = scanner.nextLine();
this.anno = scanner.nextLine();
String linea;
scanner.nextLine(); //salta la prima linea ***accessori***
while(!(linea = scanner.nextLine()).equals("***accessori***")) {
listaAccessori.add(linea);
}
Con questa roba qui e uno Scanner aperto su un file nel formato già citato, la creazione dell'elenco di automobile diventa:
while(scanner.hasNextLine()) {
DatiInizializzazioneAuto dati = new DatiInizializzazioneAuto(scanner);
Auto auto = new Auto(dati);
listaAuto.add(auto); //listaAuto è un ArrayList<Auto>
}
Il codice sorgente del tuo programma deve essere una rappresentazione diretta e fedele del sistema che vuoi creare, per come tu l'hai inteso.
Evitare di scrivere troppo codice è l'assillo del programmatore-fruttivendolo. Qui non si vende un tanto al kilo: ci vogliono le linee che ci vogliono.
Facendo in questo modo la classe auto è sempre questa:
[CODE]
/** Questa classe rappresenta un'automobile. */
class Auto {
private String costruttore;
private String modello;
private String versione;
private String anno;
private ArrayList<String> accessori;
/** Le istanze di Auto sono inizializzate usando un pacchetto di informazioni
di tipo DatiInitializzazioneAuto. */
public Auto(DatiInizializzazioneAuto dati) {
costruttore = dati.getCostruttore();
modello = dati.getModello();
versione = dati.getVersione();
anno = dati.getAnno();
accessori = new ArrayList<String>(dati.getAccessori());
}
public String getCostruttore() {
return costruttore;
}
public String getModello() {
return modello;
}
public String getVersione() {
return versione;
}
public String getAnno() {
return anno;
}
public Collection<String> getAccessori() {
return accessori;
}
[\CODE]
MENTRE I METODI DELLA CLASSE DATIINIZIALIZZAZIONE AUTO CON L'ASTERISCO NON SERVONO + GIUSTO?
[CODE]
class DatiInizializzazioneAuto {
private String costruttore;
private String modello;
private String versione;
private String anno;
***private LinkedList<String> accessori = new LinkedList<String>();***
***public void setCostruttore(String costruttore) {***
this.costruttore = costruttore;
}
public String getCostruttore() {
return costruttore;
}
***public void setModello(String modello) {***
this.modello = modello;
}
public String getModello() {
return modello;
}
**public void setVersione(String versione) {**
this.versione = versione;
}
public String getVersione() {
return versione;
}
**public void setAnno(String anno) {**
this.anno = anno;
}
**public String getAnno() {**
return anno;
}
**public void aggiungiAccessorio(String accessorio) {**
accessori.add(accessorio);
}
**public Collection<String> getAccessori() {
return accessori;****
}
}
[\CODE]
Direi di no. DatiInizializzazioneAuto e Auto non perdono pezzi. Devi solo aggiungere a DatiInizializzazioneAuto il costruttore:
public DatiInizializzazioneAuto(Scanner scanner) {
this.costruttore = scanner.nextLine();
this.modello = scanner.nextLine();
this.versione = scanner.nextLine();
this.anno = scanner.nextLine();
scanner.nextLine();
String line;
while(!(line = scanner.nextLine()).equals("***accessori***")) {
accessori.add(scanner.nextLine());
}
}
Ora che succede. Succede che se crei uno Scanner sul file che contiene i dati delle automobili, nel formato:
costruttore
modello
versione
anno
***accessori***
zero o più linee
***accessori***
costruttore
modello
versione
anno
***accessori***
zero o più linee
***accessori***
eccetera...
puoi estrarre i dati delle singole automobili, nella classe che dovrà contenere le automobili, probabilmente un DAO, semplicemente dicendo:
ArrayList<Auto> autoNelFile = new ArrayList<Auto>();
while(scanner.hasNextLine()) {
DatiInizializzazioneAuto dati = new DatiInizializzazioneAuto(scanner);
autoNelFile.add(new Auto(dati));
}
Potresti anche eliminare DatiInizializzazioneAuto e trasferire la creazione tramite Scanner in Auto ma così facendo trasferiresti in Auto un procedimento di inizializzazione meramente eventuale. Nel senso che se i dati venissero da un database anzichè da un file dovresti poi, per coerenza, aggiungere ad Auto un secondo costruttore che usi non uno Scanner ma una Connection o simili. Sotto questo profilo, DatiInizializzazioneAuto ci permette di separare la concreta procedura di inizializzazione dello stato di un'Auto dal possesso di uno stato iniziale.
Ripeto, la classe Auto non subisce modifiche. La classe DatiInizializzazioneAuto vede l'aggiunta di un nuovo costruttore che prende uno Scanner. Questo costruttore viene aggiunto non perchè sia tecnicamente necessario, poche cose lo sono, ma per evitare di dover scrivere all'interno del ciclo while su riferito quelle dieci linee di codice che concretamente estraggono i dati dal file.
Un post scriptum.
La faccenda del DatiInizializzazioneAuto non è un imperativo categorico. Se a un certo punto vedi che non ti quaglia, devi cercare una soluzione che ti suoni meglio.
stregone_giallo_rosso
06-07-2007, 11:55
Puoi farmi vedere questo per il file:
""Potresti anche eliminare DatiInizializzazioneAuto e trasferire la creazione tramite Scanner in Auto "" in modo che vedo entrambi così capisco meglio perchè non va bene!!! ti ringrazio
Questo è il file con le auto:
fiat
panda
base
1986
***accessori***
volante
pedali
***accessori***
bmw
301
aero
1834
***accessori***
tettuccio apribile
scacciamosche
***accessori***
Questa è la classe automobile senza DatiInizializzazioneAuto:
import java.util.*;
public class Auto {
private String costruttore, versione, modello, anno;
private LinkedList<String> accessori = new LinkedList<String>();
public Auto(Scanner in) {
costruttore = in.nextLine();
modello = in.nextLine();
versione = in.nextLine();
anno = in.nextLine();
String line = in.nextLine();
while(!(line = in.nextLine()).equals("***accessori***")) {
accessori.add(line);
}
}
public String getCostruttore() { return costruttore; }
public String getVersione() { return versione; }
public String getModello() { return modello; }
public String getAnno() { return anno; }
public Collection<String> getAccessori() { return accessori; }
}
Questo è un main per provare:
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Throwable {
Scanner in = new Scanner(new File(args[0]));
while(in.hasNextLine()) {
print(new Auto(in));
}
}
private static void print(Auto a) {
System.out.println(a.getCostruttore());
System.out.println(a.getModello());
System.out.println(a.getVersione());
System.out.println(a.getAnno());
for(String s : a.getAccessori()) {
System.out.println("\t" + s);
}
}
}
stregone_giallo_rosso
06-07-2007, 14:06
Questo è il file con le auto:
fiat
panda
base
1986
***accessori***
volante
pedali
***accessori***
bmw
301
aero
1834
***accessori***
tettuccio apribile
scacciamosche
***accessori***
Questa è la classe automobile senza DatiInizializzazioneAuto:
import java.util.*;
public class Auto {
private String costruttore, versione, modello, anno;
private LinkedList<String> accessori = new LinkedList<String>();
public Auto(Scanner in) {
costruttore = in.nextLine();
modello = in.nextLine();
versione = in.nextLine();
anno = in.nextLine();
String line = in.nextLine();
while(!(line = in.nextLine()).equals("***accessori***")) {
accessori.add(line);
}
}
public String getCostruttore() { return costruttore; }
public String getVersione() { return versione; }
public String getModello() { return modello; }
public String getAnno() { return anno; }
public Collection<String> getAccessori() { return accessori; }
}
Questo è un main per provare:
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Throwable {
Scanner in = new Scanner(new File(args[0]));
while(in.hasNextLine()) {
print(new Auto(in));
}
}
private static void print(Auto a) {
System.out.println(a.getCostruttore());
System.out.println(a.getModello());
System.out.println(a.getVersione());
System.out.println(a.getAnno());
for(String s : a.getAccessori()) {
System.out.println("\t" + s);
}
}
}
scusami l'ultima cosa per mettere gli oggetti Auto in un ArrayList<Auto> come devo fare??
stregone_giallo_rosso
06-07-2007, 15:01
io ho provato cosi ma non va :
[code]
import java.io.*;
import java.util.*;
class Let{
public Let()throws Exception {
Scanner in = new Scanner(new File("auto1.txt"));
ArrayList<Auto> al = new ArrayList<Auto>();
while(in.hasNextLine()) {
print(new Auto(in));
al.add(new Auto(in));
}
}
public void cerca (String costr){
for(int i=0;i<al.size();i++){
if(al.get(i).getCostruttore().equalsIgnoreCase(costr))
System.out.println(al.get(i).getVersione());}
}
private static void print(Auto a) {
System.out.println(a.getCostruttore());
System.out.println(a.getModello());
System.out.println(a.getVersione());
System.out.println(a.getAnno());
for(String s : a.getAccessori()) {
System.out.println("\t" + s);
}
}
private ArrayList<Auto> al;
}
[\code]
Puoi usare il metodo add dell'ArrayList.
ilMioArrayListDiAuto.add(un'Auto);
Ho come il sospetto che di Java non vi abbiano spiegato una mazza e siate stati mandati allo sbaraglio.
Nel corpo del costruttore di Let dichiari un ArrayList<Auto> di nome al. Per riempire quell'ArrayList, nel tuo ciclo while devi mettere al posto di print(new Auto(in))
Auto auto = new Auto(in);
al.add(auto);
print(auto); //se vuoi stampare a video l'automobile
La classe Let dichiara poi un campo di nome al e tipo ArrayList<Auto>. Nota bene che questo campo di nome al e di tipo ArrayList<Auto> è tutt'altra cosa rispetto alla variabile locale di nome al e di tipo ArrayList<Auto> dichiarata e inizializzata nel corpo del costruttore di Let.
Vale a dire che se nel ciclo while metti le linee di codice che ti ho indicato, sarà la variabile locale al a "riempirsi" di Auto mentre il campo "al" non sarà minimamente influenzato dalle sorti della variabile locale.
Se vuoi che sia il campo "al" a riempirsi, allora devi rimuovere la dichiarazione di variabile nel corpo del costruttore. Da
ArrayList<Auto> al = new ArrayList<Auto>();
a:
al = new ArrayList<Auto>();
Nel secondo caso (parliamo sempre del corpo del costruttore) il compilatore ricondurrà il nome "al" al campo "al" delle istanze di Let. Alternativamente puoi inizializzare il campo "al" all'atto della dichiarazione:
private ArrayList<Auto> al = new ArrayList<Auto>();
A questo punto il costruttore non avrà più la necessità di inizializzare il campo e la linea:
al = new ArrayList<Auto>() andrà eliminata.
stregone_giallo_rosso
06-07-2007, 15:17
ho provato come hai detto , non va!!!!! non mi trova la versione a partire dal costr:cry:
Se dico a non è b, c, magari d, è a e basta :D.
Debitamente corretto, il tuo codice fa quanto dovrebbe:
import java.io.*;
import java.util.*;
public class Let {
private ArrayList<Auto> al = new ArrayList<Auto>();
public Let()throws Exception {
Scanner in = new Scanner(new File("z:\\auto.txt"));
while(in.hasNextLine()) {
Auto auto = new Auto(in);
al.add(auto);
}
cerca("BMW"); //Esempio di ricerca
}
public void cerca (String costr){
for(int i=0;i<al.size();i++){
if(al.get(i).getCostruttore().equalsIgnoreCase(costr)) {
System.out.println("Trovato: " + al.get(i).getVersione());
}
}
}
private static void print(Auto a) {
System.out.println(a.getCostruttore());
System.out.println(a.getModello());
System.out.println(a.getVersione());
System.out.println(a.getAnno());
for(String s : a.getAccessori()) {
System.out.println("\t" + s);
}
}
}
stregone_giallo_rosso
06-07-2007, 15:40
si ho fatto cosi ma non va, questo è il file:
alfa romeo
gt
1.9 tdi
2006
***accessori***
VETRI
SPAZZOLE
VETRY OSCURATI
CLIMATIZZATORE
***accessori***
audi
a3
2.0 tdi
2007
***accessori***
CERCHI 17
VETRU PRIVACY
***accessori***
audi
a5
2.5 tdi
2007
***accessori***
Q2
FARI XEON
CAMBIO AUTOMATICO
CLIMA
TERGI
CRISTALLI
PANORQMA
***accessori***
se scrivo alfa romeo mi stampa il modello gt, mentre se scrivo audi non stampa niente invece dovrebbe stampare a3 e a5
Il costruttore che cerchi non è:
"audi"
ma
"audi "
Con uno spazio in fondo. Cioè nel file non esiste il costruttore di nome "audi" e basta, c'è uno spazio vuoto in più. Se cerchi "audi ", con lo spazio in fondo, trovi le tue versioni.
E' un problema di definizione del formato. Auto prende come costruttore l'intera linea, inclusi eventuali spazi bianchi, tabulazioni e quant'altro.
stregone_giallo_rosso
06-07-2007, 15:58
grazie col tuo aiuto sono riuscito a capire qualkosa di java...thanks:D
stregone_giallo_rosso
07-07-2007, 14:52
ciao un ultima cosa , nel metodo cerca vorrei fare in modo che digitando un numero mi stampi la versione corrispondente, ho provato con il switch , ma le auto fossero a centinaia sarebbe un pò lungo:D , sapresti un modo per impostarlo meglio???
es.
Inserisci costruttore:
audi
1 a3
2 a5
Scegli:
2
1 2.5Tdi
digita la versione
1
stampa scheda auto
questo è il met cerca:
public void cerca (){
Scanner in = new Scanner (System.in);
System.out.println("Inserisci il costruttore:");
String costr =in.nextLine() ;
for(int i=0;i<al.size();i++){
if(al.get(i).getCostruttore().equalsIgnoreCase(costr)){
System.out.flush();
System.out.println(i+"."+" "+al.get(i).getModello());}
}
}
stregone_giallo_rosso
07-07-2007, 17:13
e se non ti dispiace puoi fare un interfaccia grafica che inserendo il nome del costruttore e premendo il button cerca stampi la lista di tutti e modelli che cliccando sopra a un modello stampi la lista di tutte le versioni e cliccando sulla versione stampi l'auto completa.........please!!!!!:muro:
Per la scelta indicizzata potresti fare in questo modo. Quando l'utente seleziona il costruttore tu prendi tutti modelli di quel costruttore e li metti in un ArrayList<Auto> temporaneo. Dopodichè proponi all'utente il contenuto di quell'ArrayList:
ArrayList<Auto> lista = un array list con dentro tutti i modelli del costruttore scelto;
System.out.println("Scegli un modello.");
for(int i = 0; i < lista.size(); i++) {
System.out.println(i + ") " + lista.get(i).getModello());
}
int indice = numero scelto dall'utente.
Auto autoSelezionata = lista.get(indice);
Le ovvie e già citate ragioni non posso fornirti il codice dell'interfaccia.
stregone_giallo_rosso
07-07-2007, 18:33
solo a scopo dimostrativo
stregone_giallo_rosso
07-07-2007, 18:44
cosi???
public void cerca (){
Scanner in = new Scanner (System.in);
System.out.println("Inserisci il costruttore:");
String costr =in.nextLine() ;
for(int i=0;i<al.size();i++){
if(al.get(i).getCostruttore().equalsIgnoreCase(costr))
System.out.println(i+"."+" "+al.get(i).getModello());
ArrayList<Auto> lista = new ArrayList<Auto>();
lista.add(al.get(i).getModello());
System.out.println("Scegli un modello.");}
for(int i = 0; i < lista.size(); i++) {
System.out.println(i + ") " + lista.get(i).getModello());
}
int indice = in.nextInt();
Auto autoSelezionata = lista.get(indice);
}
stregone_giallo_rosso
09-07-2007, 09:08
ma non funziona!!!!!
Quando incolli del codice sorgente racchiudilo tra i tag
[code] [/code]
Così preserverai l'indentazione.
Il metodo cerca è ok, devi solo spostare la dichiarazione dell'ArrayList lista fuori dal ciclo e usare lista.add(al.get(i)) anzichè lista.add(al.get(i).getModello())
public void cerca (){
ArrayList<Auto> lista = new ArrayList<Auto>();
Scanner in = new Scanner (System.in);
System.out.println("Inserisci il costruttore:");
String costr =in.nextLine() ;
for(int i=0;i<al.size();i++){
if(al.get(i).getCostruttore().equalsIgnoreCase(costr)) {
System.out.println(i+"."+" "+al.get(i).getModello());
lista.add(al.get(i));
}
}
System.out.println("Scegli un modello.");
for(int i = 0; i < lista.size(); i++) {
System.out.println(i + ") " + lista.get(i).getModello());
}
int indice = in.nextInt();
Auto autoSelezionata = lista.get(indice);
print(autoSelezionata);
}
stregone_giallo_rosso
10-07-2007, 16:26
Ciao ho un'altra cosa da chiederti. Ho un ArrayList contenente oggetti pesona
vorrei ordinarlo per cognome, con il metodo Collection.sort() ma non va! come mai? me lo puoi postare? grazie
Supponendo che l'oggetto Persona abbia un metodo getCognome(), l'ordinamento di un ArrayList di Persona potrebbe essere ottenuto con:
Comparator<Persona> comparatore = new Comparator<Persona>() {
public int compare(Persona a, Persona b) {
return a.getCognome().compareTo(b.getCognome());
}
};
Collections.sort(lista, comparatore);
Qui "lista" è il tuo ArrayList di riferimenti Persona.
stregone_giallo_rosso
10-07-2007, 17:10
la classe comparator si deve fare per forza? se è si come???
Nell'esempio, comparatore è un'istanza di una classe interna anonima che concretizza l'interfaccia Comparator<Persona>.
L'alternativa è dotare la classe Persona di un ordine naturale. Per farlo devi modificare Persona in modo tale che concretizzi l'interfaccia Comparable<Persona>. Ciò richiede che la classe Persona sia dotata di un metodo di questo tipo:
public int compare(Persona that) {
return this.getCognome().compareTo(that.getCognome());
}
Dotare Persona di ordine naturale ti consente di sfruttare il metodo sort(List) di Collections:
Collections.sort(lista);
dove lista è l'ArrayList<Persona>.
stregone_giallo_rosso
11-07-2007, 16:38
Ecco qua! ho fatto sia la classe Persona(ovvero Name) che la classe Ordina .
Perchè non funziona..........c'è sicuro qulache errore, puoi controllare?
Codice Name:
import java.util.Scanner;
class Name {
public Name(String nome,String cognome){
this.nome = nome;
this.cognome= cognome;
}
public String getNome(){
return nome;
}
public String getCognome(){
return cognome;
}
public static Name read(Scanner in) throws Exception{
if(!in.hasNext()) return null;
return new Name(in.nextLine(), in.nextLine());
}
public int compareTo(Name that) {
return this.getCognome().compareTo(that.getCognome());
}
private String nome, cognome;
}
e qui il codice Ordina:
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class Ordina {
public Ordina(String file)throws Exception{
Scanner in =new Scanner(new FileReader(file));
ArrayList<Name> a = new ArrayList<Name>();
Name n = Name.read(in);
while(n!=null){
a.add(n);
n = Name.read(in);
}
in.close();
n.compareTo(n);
Collections.sort(a);
}
}
Nel codice che hai, hai anche dichiarato:
class Name implements Comparable<Name> {
?
stregone_giallo_rosso
12-07-2007, 08:21
si
stregone_giallo_rosso
12-07-2007, 11:07
e se hanno cognomi uguali e nomi diversi
Se Name è un comparable<Name> allora quel Collections.sort(a) non può che ordinare i nomi. In che senso non va? Non te li ordina? Sarebbe un bel mistero.
Cognomi uguali e nomi diversi. Non so se sia corretto dal punto di vista semantico ma potresti dire che nel caso in cui i cognomi sono uguali allora ordini rispetto al nome.
public int compareTo(Name that) {
int value = this.getCognome().compareTo(that.getCognome());
if(value == 0) {
value = this.getNome().compareTo(that.getNome());
}
return value;
}
A mo' di nota dovrei dirti che se vuoi comparare due stringhe che rappresentano dei nomi in un certo linguaggio allora dovresti usare non il metodo compareTo di String ma il metodo compare di Collator. Ma non so se questa "tecnicalità" ti possa interessare.
stregone_giallo_rosso
14-07-2007, 14:54
Scusa se ti assillo!!! MI potresti fare una panoramica sulla classe HashSet con i relativi metodi e se puoi un esempio??? grazie
HashSet è un Set, cioè un insieme che non contiene duplicati.
Dato un oggetto pippo, il suo duplicato è l'oggetto ciccio se ciccio.equals(pippo) è true.
HashSet usa una hashmap per conservare i valori. Per il programmatore significa che gli oggetti inseriti devono avere codici hash diversi se sono diversi e uguali se sono uguali.
Il codice hash di un oggetto è il valore (int) restituito dal suo metodo hashCode().
HashSet ha tre metodi di interesse.
add, remove e contains. Add aggiunge un elemento se non è gia stato inserito. remove rimuove un elemento già inserito. contains restituisce true se l'insieme contiene l'elemento in argomento.
Fine dell'hashset.
Ricorda che il valore restituito dal metodo hashCode di un oggetto Java dovrebbe seguire le sorti del metodo equals. Vale a dire che due oggetti a e b per cui a.equals(b) è true dovrebbero anche avere uguali codici hash, cioè a.hashCode() == b.hashCode().
Prendiamo ad esempio una Persona.
public class Persona {
private String nome;
private String cognome;
public String getNome() { return nome; }
public String getCognome() { return cognome; }
}
E' possibile creare un oggetto HashSet<Persona> e inserire delle persone:
HashSet<Persona> set = new HashSet<Persona>();
Persona gianni = new Persona("gianni", "rossi");
Persona mario = new Persona("mario", "verdi");
set.add(gianni);
set.add(mario);
Qui set.contains(gianni); vale true e set.contains(mario) anche. La faccenda funziona perchè Persona riceve i metodi equals ed hashCode definiti in Object. I due metodi di Object sono, da un punto di vista orientato agli oggetti, immondi. Dichiarano che un oggetto è uguale ad un altro se risiede allo stesso indirizzo di memoria.
Se prendiamo la nostra Persona appare quasi evidente l'uguaglianza per indirizzo sia a dir poco bizzarra: una Persona possiede due caratteri, il nome ed il cognome, ma sarebbe uguale ad un altra in virtù di un terzo valore, l'indirizzo di memoria, del quale poco sappiamo, ancor meno vogliamo sapere e soprattutto nulla possiamo fare.
Se intendiamo usare la capacità di Persona di dichiarare la sua uguaglianza con un'altro oggetto, e per HashSet questo è necessario, allora dobbiamo anche stabilire un significato di uguaglianza che sia coerente con la rappresentazione di una Persona.
Possiamo scegliere se usare il nome, il cognome od entrambi ma il minimo che ci si può aspettare è che una Persona sia uguale ad un'altra se le loro definizioni coincidano, in tutto o in parte.
Noi prendiamo tutto quanto: nome e cognome. Stabiliamo che due persone sono uguali se i loro nomi ed i loro cognomi coincidano.
La storia è simile a quanto hai già fatto per "compareTo" ma stavolta si tratta di ridefinire i metodi equals e hashCode. Il metodo equals restituirà true se questa persona e quell'altra abbiano lo stesso nome e lo stesso cognome:
public class Persona {
private String nome;
private String cognome;
public Persona(String nome, String cognome) {
this.nome = nome;
this.cognome = cognome;
}
public String getNome() {
return nome;
}
public String getCognome() {
return cognome;
}
public boolean equals(Object o) {
//se "o" è una Persona
if(o instanceof Persona) {
Persona that = (Persona)o;
//restituisce true se il nome di questa persona è uguale
//al nome di quella e il cognome di questa persona è
//uguale al cognome di quella
return
this.getNome().equals(that.getNome()) &&
this.getCognome().equals(that.getCognome());
} else {//se o non è una persona...
return false;
}
}
public int hashCode() {
...vediamo dopo;
}
}
Il metodo hashCode è concettualmente simile. Restituisce un numero intero. Il numero restituito può essere uno qualsiasi, 1, duemila, meno tre miliardi, è indifferente. Ciò che conta è che due oggetti che risultino uguali secondo il metodo equals restituiscano anche lo stesso numero come codice hash. Se sono diversi, devono restituire un numero diverso.
Nel caso di Persona, quindi, il nostro numero intero deve essere uguale per ogni coppia di stringhe (nome, cognome) uguali, perchè sono queste due stringhe che determinano l'uguaglianza tra due Persona.
Una possibile versione del metodo hashCode per Persona è questa:
public int hashCode() {
long hashNome = getNome().hashCode();
long hashCognome = getCognome().hashCode();
long longHash = (hashNome << 32) + hashCognome;
return new Long(longHash).hashCode();
}
Dovendo restituire un intero a 32 bit che sia uguale per Persone uguali, fa questo:
1. prende il codice hash (intero, 32 bit) del nome.
2. prende il codice hash (intero, 32 bit) del cognome.
3. crea un numero a 64 bit composto da [nome][cognome]
4. restituisce il codice hash di quel numero a 64 bit.
Il metodo sfrutta la proprietà del metodo hashCode di String che dichiara di restituire numeri uguali per sequenze di caratteri uguali e il comportamento predefinito del metodo hashCode di Long, che restituisce a sua volta int uguali per long uguali.
La faccenda va presa cum grano salis. Il codice hash è un intero a 32 bit. Due codici hash di due stringhe combinati fanni un intero a 64 bit. Riducendo questi 64 bit a 32 è ovvio che sussista la possibilità di collisioni. Cioè è possibile che Persone dal nome diverso restituiscano codici hash uguali. Se il numero di persone è tuttavia limitato (relativamente, qualche centinaio di milioni) le probabilità che si verifichi una collisione sono piuttosto basse.
Nel caso in cui il numero di persone sia elevato (miliardi) allora dovrai definire un codice hash più ampio. Essendo il codice hash a 32 bit usato per definizioni dalla mappa di HashSet, dovrai anche creare un nuovo HashSet.
La Persona vista all'inizio e la Persona con i metodi hashCode ed equals sovrascritti si comportano in modo diverso quando sono usati in un HashSet. Con la prima persona:
HashSet<Persona> set = new HashSet<Persona>();
set.add(new Persona("gianni", "rossi"));
set.contains(new Persona("gianni", "rossi")); <-- FALSO
Falso perchè istanze diverse sono allocate in aree di memoria diverse.
Ma con la seconda Persona e gli stessi enunciati:
HashSet<Persona> set = new HashSet<Persona>();
set.add(new Persona("gianni", "rossi"));
set.contains(new Persona("gianni", "rossi")); <---VERO
Vero perchè noi, tramite i metodi hashCode ed equals, abbiano stabilito che due persone sono uguali quanto abbiano nome e cognome uguali.
Per dubbi, domande, perplessità...sai dove trovarmi.
stregone_giallo_rosso
19-07-2007, 11:46
Grazie!!!! Come si fa a ordinare un HashSet???
L'HashSet non è ordinabile.
Puoi usare un TreeSet al posto dell'HashSet oppure creare una vista ordinata del contenuto dell'HashSet.
Per la seconda:
ArrayList<X> lista = new ArrayList<X>(hashSet);
Collections.sort(lista);
La scelta è una questione di compromessi.
Le operazioni aggiungi, rimuovi e contiene in un HashSet sono eseguite più rapidamente delle corrispondenti operazioni su un TreeSet.
D'altro canto, ordinare un HashSet richiede la creazione di un nuovo elenco di riferimenti mentre un TreeSet è ordinato per natura.
La scelta migliore è il frutto di un'analisi statistica del comportamento dell'applicazione.
Se l'applicazione esegue per lo più aggiunte rimozioni e verifiche di contenimento allora l'HashSet è preferibile al TreeSet. D'altro canto è possibile che il maggiore spazio in memoria richiesto per la creazione di una vista ordinata sull'HashSet non sia sopportabile. Se l'operazione prevalente dipende dall'ordinamento la maggiore onerosità in accesso al TreeSet può essere positivamente bilanciata dal fatto che il suo contenuto è costantemente ordinato.
Tecnicamente sono numeri. Calcoli quanti accessi e quanti ordinamenti farai, moltiplichi per il costo di accesso e ordinamento, sia in termini di memoria che in termini di rapidità di esecuzione, poi valuti quale soluzione sia obiettivamente migliore.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.