Prima questione: ArrayList o Vector ?
ArrayList è più veloce di Vector.
La differenza è data dal fatto che Vector è sincronizzata. La differenza di velocità è notevole nel caso di accesso contemporaneo da due thread e trascurabile per accessi non contemporanei.
La regola che uso è: ArrayList sempre, a meno che non ci sia la necessità di avere la sincronizzazione.
Per misurare la velocità in caso di accessi non contemporanei, prova:
codice:
import java.util.List;
import java.util.Vector;
import java.util.ArrayList;
import java.util.Iterator;
public class TestVelocita {
public static void main (String[] args) {
List lista;
int n = 5000000;
int i;
long elapsed;
Object o = new Object();
if (args.length==0) {
System.out.println("Uso: java TestVelocita [vector|arraylist] [numero oggetti]");
} else {
if (args[0].toUpperCase().equals("VECTOR")) {
lista = new Vector();
} else {
lista = new ArrayList();
}
if (args.length==2) {
n = Integer.parseInt(args[1]);
}
elapsed=System.currentTimeMillis();
for (i=0; i<=n; i++) {
lista.add(o);
}
elapsed=System.currentTimeMillis()-elapsed;
System.out.println("Tempo di inserimento: " + elapsed + " ms");
elapsed=System.currentTimeMillis();
for (i=0; i<=n; i++) {
o=lista.get(i);
}
elapsed=System.currentTimeMillis()-elapsed;
System.out.println("Tempo di accesso sequenziale tramite indice: " + elapsed + " ms");
elapsed=System.currentTimeMillis();
for (Iterator iter=lista.iterator(); iter.hasNext(); ) {
o=iter.next();
}
elapsed=System.currentTimeMillis()-elapsed;
System.out.println("Tempo di accesso sequenziale tramite Iterator: " + elapsed + " ms");
}
}
}
Sulla mia macchinetta è:
D:\Sviluppo\Test>java TestVelocita vector
Tempo di inserimento di 5000000 oggetti: 468 ms
Tempo di accesso tramite indice a 5000000 oggetti: 94 ms
Tempo di accesso tramite Iterator a 5000000 oggetti: 250 ms
D:\Sviluppo\Test>java TestVelocita arraylist
Tempo di inserimento di 5000000 oggetti: 641 ms
Tempo di accesso tramite indice a 5000000 oggetti: 79 ms
Tempo di accesso tramite Iterator a 5000000 oggetti: 234 ms
Quando ho tempo, faccio un programmino di prova da due thread contemporaneamente.
Seconda questione
Se nella hashtable come chiave memorizzo un indice che funge da contatore, posso sviluppare cosi il for?
codice:
for (int i = 0 ; i < table.size(); i++)
{
oggetto o=table.get(i);
}
No: le chiavi sono oggetti, non int. HashTable non ha un metodo get(int index), ma ha il metodo get (Object o).
Dunque devi fare:
codice:
for (int i = 0 ; i < table.size(); i++)
{
Object o=table.get(new Integer(i));
}
e hai in più l'overhead della creazione di un Integer.
Per HashTable e HashMap, vale la stessa considerazione fatta per Vector e ArrayList: usa sempre la seconda, a meno che non ti serve la sincronizzazione.
Nelle applicazioni che non usano queste Collection in modo particolarmente spinto, la questione è comunque puramente accademica, in quanto non si noterebbe comunque la differenza tra le diverse implementazioni. La regola è di non ottimizzare codice già scritto a meno che non si notano problemi prestazionali o a meno che non stai scrivendo codice per farlo vedere a un professore.
Terza questione
Il metodo get() di una List non è detto che sia velocissimo: il get() un ArrayList è imbattibile, perché è come accedere un array. Il get() di LinkedList può essere lento, perchè deve scorrere tutta la lista. Il get() di HashTable (o HashMap) usa prima l'hashcode dell'oggetto per restringere la ricerca a un solo bucket (l'insieme degli oggetti che hanno lo stesso hashcode) e poi ricerca la chiave: può avere prestazioni intermedie. Comunque ripeto che ArrayList (che è una List) e HashTable (che è una Map) non sono confrontabili, perchè sono strutture diverse e si usano in condizioni diverse.