Superdreadnought
Anmeldungsdatum: 31. Mai 2006
Beiträge: 563
|
Ich würde gerne auf die Variablen und Funktionen einer Klasse, die als ein Objekt in einem Vector sitzt (keine Ahnung, ob ich das jetzt 100% Java-Grammatikalisch richtig ausgedrückt hab) zurückgreifen. Vector DB = new Vector();
DB.addElement(new DatabaseItem());
System.out.println(DB.lastElement().info); (info ist eine der Variablen meiner DatabaseItem Klasse)
Hab ne halbe stunde geggogelt und einiges ausprobiert, hab aber leider keine lösung zu meinem problem gefunden. Schon ma danke für eure Hilfe.
|
dafi81
Anmeldungsdatum: 26. März 2005
Beiträge: 89
|
Auf den ersten Blick würd ich sagen ab Java 1.5 sonst ein Cast:
Vector<DatabaseItem> db = new Vector<DatabaseItem>();
db.addElement(new DatabaseItem());
System.out.println(db.lastElement().info); versuchs mal lg
|
fnumatic
Anmeldungsdatum: 20. Februar 2007
Beiträge: 379
|
Vector sollte man nicht mehr verwenden hier ein Beispiel mit einer Liste
List<InfoObject> list = new ArrayList();
list.add( new InfoObject() );
list.add( new InfoObject() );
// über liste iterieren
for (InfoObject infoObject : list) {
infoObject.printMessage();
}
//wahlfreier Zugriff
list.get(0).printMessage();
|
dafi81
Anmeldungsdatum: 26. März 2005
Beiträge: 89
|
Warum sollte man keinen Vector verwenden (the fail-fast behavior of iterators) ? Oder was meinst du? lg
|
fnumatic
Anmeldungsdatum: 20. Februar 2007
Beiträge: 379
|
As of the Java 2 platform v1.2, this class has been retrofitted to implement List, so that it becomes a part of Java's collection framework. Unlike the new collection implementations, Vector is synchronized. ... Note that the fail-fast behavior of an iterator cannot be guaranteed as it is
- mit anderen Worten es ist langsamer als etwa die ArrayList Implementierung. - fail-fast kann unter Umtständen von Vorteil sein, z.B. bei nebenläufigen Sachen, ist aber in der Vector Implementierung nicht garantiert. in einer nebenläufigen Phase wird vorzugsweise ein Wrapper (Collections.synchronizedInterface) benutzt.
|
Superdreadnought
(Themenstarter)
Anmeldungsdatum: 31. Mai 2006
Beiträge: 563
|
|
Hello_World
Anmeldungsdatum: 13. Juni 2006
Beiträge: 3620
|
fnumatic hat geschrieben: Vector sollte man nicht mehr verwenden
Unfug, Vector ist nicht deprecated, also kann man es auch verwenden...
|
fnumatic
Anmeldungsdatum: 20. Februar 2007
Beiträge: 379
|
Unfug, Vector ist nicht deprecated, also kann man es auch verwenden...
- prinzipiell kann man alles verwenden was vom runtime unterstützt wird, ob deprecated oder nicht. Allerdings würde ich im review die Benutzung von deprecated oder legacy Klassen immer beanstanden. Vector ist eine legacy Klasse, sie wird nur noch mitgeschleppt und fügt sich nicht oder unzureichend ins collections framework ein. Ein gegen List instanziertes ArrayList ist performanter als Vector. → Vector sollte nicht mehr verwendet werden
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17625
Wohnort: Berlin
|
Weder findet sich in der Dokumentation ein Hinweis, die Klasse sei legacy-Code (eine Altlast), noch daß sie deprecated sei. Auch kann man nicht generell sagen, ein Vector sei langsamer als eine ArrayList, obwohl das unter gewissen Umständen eher zu erwarten ist, als der umgekehrte Fall. In vielen Fällen ist es schlicht wurscht, und dann würde ich auch zur ArrayList raten, damit man damit mehr Übung hat für die Fälle, in denen es eben nicht wurscht ist. In manchen Fällen empfiehlt aber die Verwendung der Vector-Klasse - es gibt beispielsweise Swing-Componenten, die mit einem Vector zusammenarbeiten, aber keine ArrayList aktzeptieren.
|
fnumatic
Anmeldungsdatum: 20. Februar 2007
Beiträge: 379
|
Ich erwähnte nicht, dass Vector deprecated sei... Vector ist legacy. Dieser Hinweis findet sich in der Dokumentation schon ab Version 1.3 siehe: The Collections Framework, API Reference Man kann generell sagen, dass Vector langsamer ist als z.B. ArrayList relevanter Auszug aus Vector.java (Mustang) // Positional Access Operations
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return (E)elementData[index];
}
public synchronized E set(int index, E element) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
Object oldValue = elementData[index];
elementData[index] = element;
return (E)oldValue;
}
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
} Es ist in vielen Fällen nicht wurscht, sondern smell wenn Vector ohne triftigen Grund verwendet wird.
|
dentaku
Anmeldungsdatum: 31. Januar 2005
Beiträge: 3785
|
Vector ist immer langsamer als ArrayList. Wie oben schon erwähnt, ist Vector noch eine (ur-)alte Klasse der Java-API und wird nur noch aus Kompatibilitätsgründen unterstützt.Als wir im Zuge der Migration auf Java2 umgestiegen sind haben wir in einer Optimierungsphase auch alle Vector Objekte durch ArrayList getauscht (es waren sowieso alle nicht durch Nebenläufigkeit betroffen → multithreading). Und allein diese Änderung hat teilweise deutliche Performancegewinne gebracht! (Ich spreche hier von Serveranwendungen mit einigen dutzend/hundert Vectoren mit 10/100 tausenden von items.) Für fixe Längen sind natürlich arrays zu bevorzugen. Einfach selber profilen und man sieht den Unterschied! ☺
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17625
Wohnort: Berlin
|
dentaku hat geschrieben: Vector ist immer langsamer als ArrayList.
Das Problem mit solch generellen Aussagen ist, daß man nur ein einziges Beispiel braucht, um sie zu wiederlegen. Gerade wenn es keine Nebenläufigkeit im Programm gibt ist kaum ein Gewinn zu erwarten. Und wenn ein Programm nur ein Duzend Objekte in einen Vector packt braucht man nicht groß zu profilen, um zu erahnen, daß man nichts messen wird.
|
dentaku
Anmeldungsdatum: 31. Januar 2005
Beiträge: 3785
|
Und wo ist Dein Beispiel? Wenn ich sage, ArrayList ist immer schneller als Vector so liegt das in der Implementierung der beiden Collection Klassen. Die Implementierung von Vector ist nicht nur langsamer, weil sie synchronisiert ist (thread save), sondern prinzipbedingt - oder verständlicher: historisch bedingt. Leider ist das bei einigen anderen Klassen auch so, die es schon seit Java 1 gibt und auch nachträgliche Verbesserung der Implementierung oft kaum etwas geholfen hat. Natürlich ist es eine andere Frage, wie deutlich dieser Geschwindigkeitsvorteil in einer konkreten Anwendung zum tragen kommt. Wer nur ein Briefmarkenverwaltungsprogramm schreibt, dem kann es ziemlich egal sein, welche Collection er nimmt. Aber wer auf performance Wert legt, sollte auch die ALternativen kennen, die bei hohen Durchsätzen spürbare Geschwindigkeitsgewinne erzielt. (Ja, ich geb's zu: ich beschäftige mich auch sehr viel mit Optimierung bei Java Server Anwendungen und habe eben eine Serverlastige Sicht mit entsprechend grossen Datenvolumina. 😉 )
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17625
Wohnort: Berlin
|
sh VP2.sh 100000 2>&1 | bench/benchfilter.sh
Iterations:
jdk-1.6
mode client:
false 0m0.160s
false 0m0.128s
false 0m0.088s
true 0m0.080s
true 0m0.068s
true 0m0.080s
mode server:
false 0m0.100s
false 0m0.104s
false 0m0.100s
true 0m0.088s
true 0m0.092s
true 0m0.088s
jdk-1.5
mode client:
false 0m0.144s
false 0m0.160s
false 0m0.160s
true 0m0.144s
true 0m0.152s
true 0m0.152s
mode server:
false 0m0.236s
false 0m0.200s
false 0m0.228s
true 0m0.216s
true 0m0.204s
true 0m0.208s ist die Messung, und 'true' bezeichnet die Messungen, bei denen Vector benutzt wurde, false jene, bei denen eine ArrayList benutzt wurde. VP2.sh sieht etwa so aus:
A_CLASS=./VectorPerform.java
A_NAME=VectorPerform
#
echo "Iterations: "
echo "PerformanceTest" VectorPerform
jswitch.sh 16 -v
javac $A_CLASS
echo "mode client:"
time java $A_NAME 0 $1
...
time java $A_NAME 1 $1
echo "mode server:"
time java -server $A_NAME 0 $1
...
time java -server $A_NAME 1 $1
jswitch.sh 15 -v
javac $A_CLASS
echo "mode client:"
... Und hier die einfältige Klasse
import java.util.*;
public class VectorPerform
{
private static long MAX;
public VectorPerform (final boolean flag)
{
if (flag) useVectorPerform ();
else dontUseVectorPerform ();
}
public void useVectorPerform ()
{
Vector v = new Vector ();
for (int i = 0; i < MAX; ++i)
{
v.add (new Integer (i));
}
}
public void dontUseVectorPerform ()
{
ArrayList al = new ArrayList ();
for (int i = 0; i < MAX; ++i)
{
al.add (new Integer (i));
}
}
public static void main (String args[])
{
if (args.length != 2)
{
usage ("Wrong arg count, expected=2, got=" + args.length);
System.exit (1);
}
boolean flag = false;
try
{
// parseBoolean only available since 1.5
// attention! getBoolean returns a System-properties value.
flag =(0 != Integer.parseInt (args[0]));
}
catch (NumberFormatException nfe)
{
usage ("1. Argument has to be of type 'int', 0 indicating false, everything else true.");
System.exit (2);
}
try
{
MAX = Long.parseLong (args[1]);
}
catch (NumberFormatException nfe)
{
usage ("2. Argument has to be of type 'long', number of iterations.");
System.exit (3);
}
System.out.println ("" + flag);
new VectorPerform (flag);
}
public static void usage (String msg)
{
System.err.println ("Error:");
System.err.println ("\t" + msg);
System.err.println ("Usage:\tjava VectorPerform {1|0} NUM_OF_ITERATIONS");
}
} Jetzt interessiert vielleicht noch der benchfilter:
#!/bin/bash
#
# usage: sh XYbench.sh 10000 2>&1 | benchfilter.sh
#
egrep "(mode|user|true|false|jdk|Iterations)" | tr "\n" "\t" | sed 's/switching to //g;s/user//g;s/ */\t/g;s/\ttrue/\n\ttrue/g;s/\tfalse/\n\tfalse/g;s/\tjdk/\njdk/g;s/\tmode/\nmode/g'
echo Das die Klasse einfältig ist, ist kein Problem, denn es hieß ja, ArrayList sei immer schneller. Deshalb ist es auch kein Problem, daß ArrayList die Oberhand bei etwa 1 Mio. Iterationen auf meiner Maschine gewinnt, und bei 10 Mio. auch derart, daß man 'deutlich' sagen kann.
|
dentaku
Anmeldungsdatum: 31. Januar 2005
Beiträge: 3785
|
Und was soll dieser microbenchmark nun beweisen? Er beweist jedenfalls nicht, dass Vector gleich schnell oder schneller als ArrayList ist, da bei geringen Iterationen die Laufzeitumgebung (Thread switching, garbage collector, ... bis hin zu Betriebssystem Prozess scheduling runter auf CPU stack switching) einen zu grossen Einfluss auf solche Mircolaufzeiten ausüben. Und vom Aufwärmen des HotSpots auch mal abgesehen ...
|