2009-05-01 2 views
1

Я пытался использовать стандартные вещи типа сериализация, такие вещи, как:Есть ли способ сохранить объект графа, содержащий узлы и ребра?

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(); 
} ; 

Но проблема, кажется, что если мой объект s содержит любую рекурсию на все это я получаю переполнение стека. Если s - это граф, содержащий узлы и ребра (с узлами, знающими о ребрах с целью распространения активации, и ребрами, которые знают о узлах по той же причине), тогда он переполняет стек. Если я полностью уберу края и просто узлы, которые знают, о каких узлах они должны распространять активацию, то же самое происходит! Я могу даже просто попытаться сохранить ArrayList узлов, о которых знает граф, а стек снова переполняется!

Я так расстроен!

Графики не совсем странные и таинственные, конечно же, кто-то хотел сохранить один передо мной. Я вижу что-то о сохранении их в качестве XML-файлов здесь ... но если моя проблема - это рекурсивность, не будут ли у меня все те же проблемы, даже если бы я сохранил их по-другому? Я просто не могу придумать, как вы могли бы составить график, не имея связей!

Я просто делаю что-то неправильно, или это сериализация объектов менее мощная, чем я думал? Или мне нужно просто отказаться от идеи сохранения графика?

-Jenny

Редактировать, часть ОГРОМНЫЙ трассировки стека:

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) 

ответ

2

Эти рода структуры лучше всего сохраняются, как это:

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) 

без использования рекурсии. При чтении узлов создайте словарь узлов, проиндексированных их идентификатором. Затем используйте словарь, чтобы исправить края, когда они будут прочитаны. Идентификаторы не должны быть частью структуры времени выполнения объектов, они должны быть уникальными в потоке данных, когда поток написан или читается.

+0

Хм ... это действительно хорошая идея. Моя единственная проблема заключается в том, что это не повлияет на время выполнения, если у меня есть график, просматривающий все узлы и края каждый раз, когда что-то нужно сделать? Прямо сейчас это arraylist, который, чтобы найти узел с определенным идентификатором, я должен был бы перебирать все это, наихудший сценарий, который я собираюсь, хотя каждый узел (или край), который может быть сотнями тысяч! Есть ли таблицы быстрее? – Jenny

+0

* хэш-таблицы, я имел в виду. – Jenny

+0

Да, это O (1) – Hejazzman

-1

Хммм. Одним из решений было бы превратить его в java bean и использовать XMLEncoder/XMLDecoder. Это решение, которое я использовал в прошлом для сохранения и загрузки классов.

+0

Какую магию, по вашему мнению, имеет XMLEncoder? –

+0

По моему опыту, он делает какую-то связь, когда сталкивается с вещами, которые он распознает. Является ли эта магия для графиков, я не знаю, но в результате у меня в прошлом все было неправильно (и правильно). – Brian

+0

Кроме того, XMLEncoder дает несколько более полезные сообщения об ошибках, чем сериализация. – Brian

0

Java-сериализация может справляться с произвольными графами (хотя не обязательно очень эффективно). Вероятно, проблема заключается в пользовательской реализации writeObject. Возможно, может помочь фрагмент трассировки стека.

+0

Трассировка стека ОГРОМНАЯ^_^;; Я не совсем уверен, что, если что-то важно в этом. Так я отправил первую часть (это тысячи строк). Моя проблема в том, что ничего, что я пробовал, не изменило ошибку, за исключением создания узлов в вакуумом, сохраняя их в массиве, а затем не делая их графиком. Исключение в потоке "главный" java.lang.StackOverflowError \t на java.io.ObjectStreamClass.getPrimFieldValues ​​(Unknown Source) \t на java.io.ObjectOutputStream.defaultWriteFields (Unknown Source) tream.t – Jenny

+0

я отправил несколько из стек отслеживать вверх. Но ... Эм. Я могу заверить вас, что я не создал пользовательскую реализацию writeObject^_^;; Для серьезных я имею только три класса для этой вещи. – Jenny

+0

Вы пробовали небольшой график? Похоже, он пишет график с большой степенью гнездования. –

0

полезный формат сериализации вы должны рассмотреть JSON, где легко представлены словари (как это было предложено @Skizz):

JSONObject представляет собой неупорядоченный набор пар имя/значение. Его внешняя форма - это строка, завернутая в фигурные скобки с двоеточиями между именами и значениями и запятыми между значениями и именами. Внутренняя форма - это объект, имеющий методы get() и opt() для доступа к значениям по имени и методы put() для добавления или замены значений по имени. Значения могут быть любыми из следующих типов: Boolean, JSONArray, JSONObject, Number и String или объект JSONObject.NULL.

+0

У вас все еще будет глубокая вложенность. Не уверен, насколько хорошо JSON обрабатывает произвольные графики. –

+0

построить график из 2 коллекций (не рекурсивный объект), как это было предложено @Skizz. Каждая коллекция легко сериализуется с помощью JSON. – gimel

0

Сериализация Java способна обрабатывать циклические ссылки (я предполагаю, что это то, что вы подразумеваете под рекурсией), но есть известная проблема с большими графиками, описанными в here.

Не допускайте, чтобы дата статьи выкинула вас, просто следуйте цепочке комментариев после нее.

Кажется, вам понадобится использовать другой метод сериализации для этого. Несколько упоминалось, а некоторые performance metrics дают высокие оценки JSON.

Смежные вопросы