Newsgroup: it.comp.java
Titolo: Ordinare vettore di strutture in base a un campo

Salve.
Vorrei capire come ordinare
un vettore di strutture dati non semplici
in base al valore di un campo della struttura.
So che in Java non esistono le struct del C/C++
quindi devo usare una normalissima classe
con le variabili, magari pubbliche, che fanno da campi.
E poi dichiaro un vettore di N elementi di tipo classe.
Dovrebbe essere corretto cosě :
Class D  { public int a; public double b; }     (definita a parte...)
D miaD[ ] = new D [N] ;     (ovviamente N č dichiarata/definita prima)
(fin qui infatti non ho problemi di compilazione)
Il problema č che il tentativo di accesso
a qualsiasi miaD[i].a  o  miaD[i].b
produce la tipica NullPointerException.
Dove sbaglio secondo voi ?
Passando all'ordinamento, invece,
mi č parso di capire, leggendo qualche articolo,
che l'unico modo automatico piů semplice
sia  Array.sort('oggetto') .
Nei casi di vettori di strutture(classi),
č obbligatorio usare la classe Comparator ??
-> Array.sort('oggetto', 'criterio-Comparator')  ?
Come usare il Comparator ?
Grazie anticipatamente per l'attenzione.
A presto!
F. 

 F.
Googla è cerca degli esempi con la classe comparator.

 Dove sbaglio secondo voi ?
Se non risolvo prima questa parte,
non posso andare avanti :-)
Non ho bisogno che uno mi dica di usare google....
ma di uno che *sappia* darmi una soluzione.

 Come usare il Comparator ?
Comparator e' un'interfaccia che ha il metodo
int compare(T o1, T o2);
che restituisce 0 per o1 = o2, che implica o1.equals(o2) = true, un 
valore vegativo per o1 < o2 ed un valore positivo per o1 > o2.
Nel tuo caso, ammesso che la proprietà per il confronto sia D.a, volendo 
usare il metodo statico
Arrays.sort(T[] a, Comparator<? super T> c);
potrai procedere così;
Arrays.sort(miaD, new Comparator<D> {
  int compare(D o1, D o2) {
   return o1.a-o2.a;
  }
  boolean equals(Object o) {
   return D.class.isAssignable(p.getClass()) && compare(this, (D)o)==0;
  }
});
Ma non è strettamente necessario utilizzare un Comparator, sarebbe 
sufficiente che D implementi Comparable, ovvero:
Class D implements Comparable<D> {
  public int a; public double b;
  int compareTo(D o) {
   return a-D.a;
  }
  boolean equals(Object o) {
   return D.class.isAssignable(p.getClass()) && this.compareTo((D)o)==0;
  }
}
in tal caso potresti utilizzare semplicemente
Arrays.sort(miaD);


Vorrei farti presente che un news-group non e' un posto in cui le 
pretese vengano solitamente ben accette. Di norma sortiscono l'effetto 
contrario.

 Arrays.sort(miaD);
Quindi o uso Comparator
o implemento Comparable,
in particolare compareTo()  ed equals() .
Grazie mille.
Saluti.
F. 

 Arrays.sort(miaD);
Ma l'ordinamento è crescente o decrescente ?
Come impostarne il verso ?
Riporto un parziale risultato dopo il sort ...
6810952.281997913
6813555.12515723
6813778.706201464
4770403.067724989
3505235.998970227
6814012.899431418
6814009.877199273
6814621.630516427
1406.9820852348444
486483.8010825674
2872970.728649241
come puoi vedere non c'è alcun ordinamento  :-((
Grazie per l'attenzione.
A presto.
F.

 in particolare compareTo() ed equals() .
In sostanza si', se sei il padrone della classe implementare Comparable 
costa poco, se invece stai usando una classe non tua che non implementa 
Comparable, o estendi la classe implementando Comparable oppure usi un 
Comparator.

 come puoi vedere non c'è alcun ordinamento :-((
I valori che hai listato sono inequivocabilmente valori fratti, se hai 
usato il mio esempio, l'ordinamento viene fatto sulla proprieta' int a, 
che e' un intero. Se ti serve ordinare per b, che e' un double, nel 
metodo compare dovrai utilizzare la proprieta' b, ovvero (nel caso 
ascendente):
int compare(D o1, D o2)
  return o1.b==o2.b?0:o1.b>o2.b?1:-1;
}
lo stesso per il metodo compareTo nel caso Comparable


 Il javadoc di Arrays.sort lo dice: ascendente.
Io l'ho fatto come riportato di seguito e sembra andare bene.
___________________________________
class Dist implements Comparable<Dist> {
     public double dist=0.0;
     public int id=0;
  public int compareTo(Dist d) {
        if (this.dist > d.dist) return 1;
        else if (this.dist < d.dist) return -1;
        else return 0;
}
  public boolean equals(Object o) {
      return (Dist.class.isAssignableFrom(o.getClass()) && 
this.compareTo((Dist)o) == 0);
}
}
____________________________________
E l'ordinamento riesce. Per te c'è qualche errore?
Quando parlavo di 'inizalizzazione diretta nella classe' intendevo come 
riportato nel codice.
Una curiosità ... mi spiegheresti il senso della funzione 'equals()'
e della sua implementazione ?
Grazie e Ciao.
A presto.
F.

 e della sua implementazione ?
equals e' un metodo di Object, quindi anche di qualsiasi altra classe. 
Pero' Object.equals ritorna true solo se stai confrontando la stessa 
istanza, molte classi reimplementano il metodo equals per consistenza 
con cio' che quella classe rappresenta. Ad esempio String.equals ritorna 
true se il contenuto della stringa e' il medesimo, quindi:
String a = new String("pippo");
String b = new String("pippo");
a e b sono istanze distinte della stessa classe, quindi il test:
a == b rende false, mentre a.equals(b) rende true.
Lo stesso dicasi per i derivati di Number, come Double Integer etc., se 
il numero che rappresentano due Number ha lo stesso valore, il metodo 
equals ritorna true.
Poi ci sono i casi come il tuo, dove per una singolarita' applicativa 
scegli di considerare due oggetti uguali in base ad un set di proprieta'.
Un esempio classico sono le chiavi primarie di un db, ammetti ad esempio 
che un oggetto che rappresenta un record di DB sia:
class record {
int a, b, c, d, e;
}
e che la chiave primaria della tabella si composta dal set di campi a, 
b, in tal caso pare conveniente che il metodo equals di record sia:
public boolean equals(Object obj) {
   return obj != null &&
	record.class.isAssignableFrom(obj.getClass()) &&
	a == obj.a && b == obj.b;
}