2009-05-01 5 views
1

Ich habe versucht, die Standard-Serialisierung Art Dinge verwenden, Sachen wie:Gibt es eine Möglichkeit, ein Grafikobjekt mit Knoten und Kanten zu speichern?

FileOutputStream f_out; 
try { 
    f_out = new FileOutputStream("MAOS.data"); 
    ObjectOutputStream obj_out = new ObjectOutputStream (f_out);  
    obj_out.writeObject(s); 
    obj_out.flush(); 
    obj_out.close(); 

} catch (FileNotFoundException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} catch (IOException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} ; 

Aber das Problem scheint zu sein, dass, wenn mein Objekt s jede Rekursion bei ALL I enthält einen Stapelüberlauf zu bekommen. Wenn s ein Graph ist, der Knoten und Kanten enthält (mit Knoten, die über Kanten wissen, um die Aktivierung zu verteilen, und Kanten, die aus demselben Grund Knoten kennen), dann stapeln sie einen Stapel. Wenn ich Kanten ganz herausnehme und nur Knoten habe, die wissen, über welche Knoten sie die Aktivierung auch verbreiten sollen, passiert das Gleiche! Ich kann sogar versuchen, die ArrayList der Knoten zu speichern, die der Graph kennt, und der Stapel läuft wieder über!

Ich bin so frustriert!

Graphen sind nicht gerade seltsam und mysteriös, sicherlich wollte jemand einen vor mir retten. Ich sehe etwas über das Speichern von ihnen als XML-Dateien hier ... aber wenn mein Problem die Rekursivität ist, würde ich immer noch die gleichen Probleme haben, selbst wenn ich es anders gespeichert habe? Ich kann mir einfach nicht vorstellen, wie man eine Grafik machen kann, ohne dass es Verbindungen gibt!

Mache ich nur Dinge falsch, oder ist diese Objektserialisierung weniger stark als ich dachte? Oder muss ich die Idee, ein Diagramm zu speichern, einfach aufgeben?

-Jenny

bearbeiten, Teil des riesigen Stack-Trace:

Exception in thread "main" java.lang.StackOverflowError 
    at java.io.ObjectStreamClass.getPrimFieldValues(Unknown Source) 
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source) 
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject0(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject(Unknown Source) 
    at java.util.ArrayList.writeObject(Unknown Source) 
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source) 
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject0(Unknown Source) 
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source) 
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject0(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject(Unknown Source) 
    at java.util.ArrayList.writeObject(Unknown Source) 
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source) 
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject0(Unknown Source) 
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source) 
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject0(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject(Unknown Source) 
    at java.util.ArrayList.writeObject(Unknown Source) 
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source) 
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject0(Unknown Source) 
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source) 
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source) 
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject0(Unknown Source) 
    at java.io.ObjectOutputStream.writeObject(Unknown Source) 
    at java.util.ArrayList.writeObject(Unknown Source) 
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source) 
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source) 

Antwort

2

ist diese Art von Strukturen am besten wie folgt gespeichert:

collection of nodes, each node has a unique ID 
collection of edges, each edge has two node IDs (or however many nodes an edge connects to) 

ohne jegliche Rekursion. Erstellen Sie beim Lesen der Knoten ein Wörterbuch mit Knoten, die nach ihrer ID indiziert sind. Verwenden Sie dann das Wörterbuch, um die Kanten beim Lesen zu korrigieren. Die IDs müssen nicht Teil der Laufzeitstruktur der Objekte sein, sie müssen nur innerhalb des Datenstroms eindeutig sein, wenn der Stream geschrieben/gelesen wird.

+0

Hmm .... das ist eine wirklich gute Idee. Meine einzige Sorge ist, wird das nicht wirklich Auswirkungen auf die Laufzeit haben, wenn ich nach Graphen jedes Mal, wenn etwas getan werden muss, durch alle Knoten und Kanten suchen muss? Im Moment ist es eine Arraylist, um einen Knoten mit einer bestimmten ID zu finden, müsste ich die ganze Sache durchlaufen, im schlimmsten Fall gehe ich durch jeden Knoten (oder Rand), der Hunderttausende sein könnte! Sind Tabellen schneller? – Jenny

+0

* Hash-Tabellen, meinte ich. – Jenny

+0

Ja, sie sind O (1) – Hejazzman

-1

Hmmm. Eine Lösung wäre, es zu einer Java-Bean zu machen und XMLEncoder/XMLDecoder zu verwenden. Dies ist eine Lösung, die ich in der Vergangenheit verwendet habe, um Klassen zu speichern und zu laden.

+0

Welche Magie haben Sie XMLEncoder? –

+0

Meiner Erfahrung nach führt es eine Art Verknüpfung aus, wenn es auf Dinge trifft, die es erkennt. Ob diese Magie für Graphen stattfinden wird, weiß ich nicht, aber ich habe in der Vergangenheit Dinge falsch (und richtig) gemacht. – Brian

+0

XMLEncoder gibt auch etwas hilfreichere Fehlermeldungen als Serialisierung. – Brian

0

Java-Serialisierung kann mit beliebigen Graphen umgehen (obwohl nicht unbedingt sehr effizient). Wahrscheinlich liegt das Problem bei einer benutzerdefinierten Implementierung von writeObject. Vielleicht könnte ein Abschnitt der Stapelverfolgung helfen.

+0

Die Stapelspur ist HUGE^_^;; Ich bin nicht wirklich sicher, was ist, wenn etwas wichtig ist ... Also habe ich den ersten Teil geschrieben (es ist tausende von Zeilen lang). Mein Problem ist, dass nichts, was ich ausprobiert habe, den Fehler geändert hat, nur das Erstellen von Knoten in einem Vakuum, speichert sie in einem Array und macht sie dann nicht zu einem Graphen. Exception in thread "main" java.lang.StackOverflowError \t bei java.io.ObjectStreamClass.getPrimFieldValues ​​(Unknown Source) \t bei java.io.ObjectOutputStream.defaultWriteFields (Unknown Source) tream.t – Jenny

+0

ich mehr von der entsandte Stapelverfolgung oben. Aber ... Ähm. Ich kann Ihnen versichern, dass ich keine benutzerdefinierte Implementierung von writeObject^_^;; Für ernst, ich habe nur drei Klassen für diese Sache. – Jenny

+0

Haben Sie eine kleine Grafik ausprobiert? Es sieht so aus, als ob es ein Diagramm mit einem großen Grad an Verschachtelung schreibt. –

0

Ein nützliches Serialisierungsformat man beachten sollte, ist JSON, wo Wörterbücher (wie von @Skizz vorgeschlagen) leicht vertreten:

A JSONObject ist eine ungeordnete Auflistung von Name/Wert-Paaren. Seine äußere Form ist eine Zeichenfolge, die in geschweifte Klammern mit Doppelpunkten zwischen den Namen und Werten und Kommata zwischen den Werten und Namen eingeschlossen ist. Das interne Formular ist ein Objekt mit den Methoden get() und opt() für den Zugriff auf die Werte nach Namen und put() -Methoden zum Hinzufügen oder Ersetzen von Werten nach Namen. Die Werte können folgende Typen sein: Boolean, JSONArray, JSONObject, Number und String oder das JSONObject.NULL-Objekt.

+0

Sie werden immer noch tiefe Verschachtelung haben. Nicht sicher, wie gut JSON mit beliebigen Graphen umgehen kann. –

+0

Erstellen Sie das Diagramm aus 2 Sammlungen (kein rekursives Objekt), wie von @Skizz vorgeschlagen. Jede Sammlung kann leicht mit JSON serialisiert werden. – gimel

0

Java-Serialisierung ist in der Lage, zyklische Referenzen zu behandeln (ich nehme an, das ist, was Sie mit Rekursion meinen), aber es ist ein bekanntes Problem mit großen Graphen, here beschrieben.

Lassen Sie sich vom Datum des Artikels nicht abschrecken, folgen Sie einfach der Kette von Kommentaren danach.

Es scheint, dass Sie eine andere Serialisierungstechnik verwenden müssen, um dies zu erreichen. Mehrere wurden erwähnt, und einige performance metrics geben JSON gute Noten.

Verwandte Themen