ubuntuusers.de

Java: Auf Funktion eines Objekts in einem Vector zugreifen

Status: Gelöst | Ubuntu-Version: Ubuntu 7.04 (Feisty Fawn)
Antworten |

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

ok, danke euch beiden.

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

Avatar von 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

Avatar von 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

Avatar von 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

Avatar von 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

Avatar von 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

Avatar von 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 ...

Antworten |