Java 有没有办法保存包含节点和边的图形对象?

Java 有没有办法保存包含节点和边的图形对象?,java,serialization,Java,Serialization,我尝试过使用标准的序列化类型,比如: 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(); } cat

我尝试过使用标准的序列化类型,比如:

 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文件的内容……但是如果我的问题是递归性,那么即使我以不同的方式保存它,我是否仍然会遇到同样的问题?我真想不出你怎么能在没有连接的情况下制作一个图表

我只是做错了事情,还是这个对象序列化的功能不如我想象的那么强大?还是我需要放弃保存图表的想法

-珍妮

编辑,巨大堆栈跟踪的一部分:

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)

嗯,一个解决方案是将它变成一个Javabean,并使用
XMLEncoder
/
XMLDecoder
。这是我过去用来保存和加载类的解决方案。

Java序列化可以处理任意图形(尽管不一定非常有效)。问题可能在于
writeObject
的自定义实现。也许堆栈跟踪的一部分可能会有所帮助。

这些类型的结构最好这样保存:

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)

不使用任何递归。在读取节点时,创建一个由节点ID索引的节点字典。然后在读取节点时使用字典修复边缘。IDS不需要是对象的运行时结构的一部分,当流被写入/读取时,它们只需要在数据流中是唯一的。

< P>一个有用的串行化格式应该考虑的是,字典(如@ Skizz所建议的)很容易表示:

JSONObject是名称/值对的无序集合。它的外部形式是一个用大括号括起来的字符串,名称和值之间用冒号,值和名称之间用逗号。内部表单是一个对象,它具有get()和opt()方法,用于按名称访问值,以及put()方法,用于按名称添加或替换值。这些值可以是以下任何类型:Boolean、JSONArray、JSONObject、Number和String,或者JSONObject.NULL对象


您可以使用支持将图形序列化为ML格式文本文件的库

Java序列化能够处理循环引用(我假设这就是您所说的递归),但是前面描述的大型图存在一个已知的问题

不要让文章的日期打乱了你,只需跟随文章后面的评论链即可


似乎您将不得不使用另一种序列化技术来完成此任务。已经提到了一些,其中一些给JSON打了高分。

根据我的经验,当它遇到它能识别的东西时,它会进行某种链接。我不知道这种神奇是否会发生在图形上,但我在过去也遇到过一些错误(和正确的情况)。此外,XMLEncoder提供的错误消息比序列化稍微有用一些。我不想让java bean乱来。我肯定从未接触过这项技术,我只是想用java快速绘制一个小图形。我现在正在认真考虑使用Ruby;;你不能用Java编程,也不能“从未接触过JavaBeans的技术”,就像你不能不用Ruby编码就用rails编码一样?但我的意思是,我以前从未听说过“JavaBean”这个术语。因此,我对它一无所知。如果我甚至不知道它是什么,我认为自己没有被暴露,即使它只是java。堆栈跟踪是巨大的^ ^;我真的不知道如果有什么是重要的…所以我张贴了第一部分(它的数千行长)。。我的问题是,除了在真空中创建节点、将它们存储在数组中,然后不将它们生成图形之外,我所尝试的任何东西都没有改变错误。java.io.ObjectStreamClass.getPrimFieldValues(未知源)java.io.ObjectOutputStream.defaultWriteFields(未知源)tream.tI的java.io.ObjectStreamClass.getPrimFieldValues(未知源)处的线程“main”java.lang.StackOverflower中出现异常,将更多堆栈跟踪贴到顶部。但是嗯。我可以向您保证,我没有定制writeObject的实现;;说真的,我只有三门课。你试过一个小图吗?看起来它正在编写一个嵌套程度很高的图。非常小的图不会出现堆栈溢出,但它似乎不需要在爆炸之前变得非常大。我的问题是我希望处理非常大的图,所以我需要它来处理这个^^;;因此,要么按照AbstractList的思路选择一个定制的writeObject,要么绕过它来防止如此多的递归(通过确保对象首先通过嵌套较少的递归到达)。嗯……这真是个好主意。我唯一关心的是,如果我在每次需要做任何事情时通过图形搜索所有节点和边,这不会真正影响运行时吗?现在它是一个arraylist,要找到一个具有特定id的节点,我必须迭代整个过程,最坏的情况是我要遍历每个节点(或边缘),可能是数十万个!表的速度快了吗?仍然会有很深的嵌套。不确定JSON处理任意图形的效果如何。根据@Skizz的建议,从2个集合(不是递归对象)构建图形。每个集合都很容易用JSON序列化。10年后,它仍然是相同的问题!没有Java API提出的解决方案!