`
vanadies10
  • 浏览: 82431 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java中Tree的序列化

    博客分类:
  • Java
阅读更多

工作中,遇到了在Java里面序列化一颗树、然后反序列化的时候出现Stack Overflow异常的情况。整棵树的层次和在处理每层的当前对象的消耗(在栈上的消耗)累计起来造成了Stack Overflow。
晚上在家里的时候,写了个小程序,实现了Java中对一个Tree的序列化。
这个程序主要想避免层次太深的问题,所以出发点很简单,就是要改变序列化的时候的对象关系,我们要把一个层次的关系变成平的。
这个程序完成了三个版本的序列化方式。先看第一个
第一个版本在写的时候没怎么想:大概的思路是这样的,就是我们对Tree上的每个节点独立序列化,然后我们保存节点间的父子关系,序列化后的结构数据结构是这样的:
NodeCount:4bytes
//每个节点的数据
NodeId:4bytes
Node序列化后的长度:4bytes
Node序列化后的数据:1byte*序列化后的长度
Node的Child个数:4bytes
Child的NodeId:4bytes*Child个数
......表示多个节点数据
其中,NodeId是从0开始自增

完成这个版本后,大概测试了一下,序列化后的长度比Java直接序列化多了14%左右,不爽。

思考了一下,其实NodeId是不需要的,因此,很快的改出了第二个版本,序列化后格式是这样的:
NodeCount:4bytes
//每个节点的数据
Node序列化后的长度:4bytes
Node序列化后的数据:1byte*序列化后的长度
Child的NodeId:4bytes*Child个数
......表示多个节点数据
测试了一下,长度有所减少,但是非常非常不明显,基本上是比Java序列化多了13%,还是不爽。

最后,想了一下,还是把Tree上的所有节点放到一个Array中,都交给Java序列化吧。这个时候,序列化后的格式就变为了
NodeCount:4bytes
Array序列化后的长度:4bytes
Array序列化后的内容
按照宽度优先的方式的每个TreeNode的ChildCount

这次之后,序列化后的数据和直接Java比,相差无几了,比Java直接序列化差不多少1%不到一些。

代码就放附件中了,随便写的,比较乱。

分享到:
评论
4 楼 vanadies10 2010-09-17  
jameswxx 写道
vanadies10 写道
这个tree2flat的目的,不是为了减小生成的序列化的内容的size,主要是为了避免出现Stack Overflow。把原先的深度变为了广度。


vanadies10兄,你好,不好意思,我还没有明白,stack Overflow应该指的线程栈空间内存不足吧?你说的自定义序列化避免出现Stack Overflow,指的是从序列化数据恢复对象的时候,减少对象数吗?这样子还是为了缩减所占用的内存吧


对于一棵树,我们平时去序列化的时候,是直接序列化这个树的rootNode,而如果要完成rootNode的序列化,那么是要把rootNode的各个成员都序列化好,而去序列化rootNode的各个成员,又需要去把rootNode的各个成员的成员序列化好,这个其实是个深度优先搜索的过程,并且是用递归的方式实现的,所以,在层次很深的时候,有stackoverflow的风险,并且我们是真的遇到了这个问题。
tree2flat是吧一个树变为一个扁平的数组,那么序列化数组的时候,是针对每个元素做序列化,元素之间是互相不影响的。所以,去掉了递归方式的深度优先的搜索,就不会出现stackoverflow的风险了。
3 楼 jameswxx 2010-09-16  
vanadies10 写道
这个tree2flat的目的,不是为了减小生成的序列化的内容的size,主要是为了避免出现Stack Overflow。把原先的深度变为了广度。


vanadies10兄,你好,不好意思,我还没有明白,stack Overflow应该指的线程栈空间内存不足吧?你说的自定义序列化避免出现Stack Overflow,指的是从序列化数据恢复对象的时候,减少对象数吗?这样子还是为了缩减所占用的内存吧
2 楼 vanadies10 2010-09-15  
这个tree2flat的目的,不是为了减小生成的序列化的内容的size,主要是为了避免出现Stack Overflow。把原先的深度变为了广度。
1 楼 jameswxx 2010-09-15  
   我认为即使将tree实现扁平化的序列化,也没有多大的意义,因为其实并没有比tree本身的java默认序列化减少一些字节。
   以TreeMap为例,它的序列化并没有序列化自身,请看TreeMap的writeObject方法
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
        // Write out the Comparator and any hidden stuff
        s.defaultWriteObject();

        // Write out size (number of Mappings)
        s.writeInt(size);

        // Write out keys and values (alternating)
        for (Iterator<Map.Entry<K,V>> i = entrySet().iterator(); i.hasNext(); ) {
            Map.Entry<K,V> e = i.next();
            s.writeObject(e.getKey());
            s.writeObject(e.getValue());
        }
    }

被序列化的数据基本上都是必须的

相关推荐

    java-二叉树binaryTree

    7. **树的序列化和反序列化**:将二叉树转换为字符串存储或从字符串恢复二叉树结构,是处理大型树结构时常用的方法。 在"binaryTree2"这个压缩包中,可能包含了对上述概念的实现代码,包括不同的操作方法和测试用例...

    4.Xml序列化器

    - Python:Python的`xml.etree.ElementTree`模块可用于序列化,第三方库如`PyYAML`和`pickle`也可实现。 - JavaScript:JavaScript没有内置的XML序列化,但可以借助第三方库如`xml2js`进行转换。 - PHP:PHP使用`...

    menu_tree.rar_java menutree_java treeme_java 目录树_目录树

    7. **序列化与反序列化**:为了保存和恢复目录树的状态,我们可以使用Java的序列化机制将树结构转换为字节流,然后在需要时再反序列化。然而,需要注意的是,序列化可能导致安全问题,因此在实际应用中应谨慎使用。 ...

    JAVA_API1.6文档(中文)

    javax.sql.rowset.serial 提供实用工具类,允许 SQL 类型与 Java 编程语言数据类型之间的可序列化映射关系。 javax.sql.rowset.spi 第三方供应商在其同步提供者的实现中必须使用的标准类和接口。 javax.swing 提供...

    Java写的一个Tree

    接下来,我们需要将这个树结构序列化到一个文件中。在这种情况下,选择了GBK编码的文本文件"文件清单.dat"。GBK编码兼容GB2312,能表示更多的中文字符,因此对于包含中文文件名的目录结构尤其适用。要将树结构写入...

    fanyi_java_tree9zf_fanyi.Baidu.com_mightg2h_

    5. **数据序列化与反序列化**:由于API返回的是JSON或XML格式的数据,开发者需要解析这些数据以获取翻译结果,可能用到Gson或Jackson库。 6. **错误处理与异常捕获**:良好的用户体验需要考虑网络错误、API错误等...

    Java 的对象永续之道

    文章通过具体的例子展示了序列化的强大之处,例如将复杂的数据结构如树(Tree)和哈希表(Hashtable)序列化到文件中,然后在下次执行程序时可以从文件中读取这些对象并恢复它们的状态。这对于简化代码、提高复用性和...

    xml binary soap 序列化

    5. 实现与库:许多编程语言都提供了支持XML和SOAP二进制序列化的库或框架,例如.NET Framework的BinaryFormatter和XmlSerializer,Java的XMLEncoder和XMLDecoder,Python的pickle模块和xml.etree.ElementTree等。...

    javabitset源码-array-tree-table:基于二维数据,支持排序,支持序列化/反序列化的guavatable实现

    反序列化支持(guava中的table均不支持或没有序列化器支持) 基本使用 1.使用代码 //创建起相应的类 ArrayTreeTable table = new ArrayTreeTable&lt;&gt;(String.class, String.class, String.class, (Class) String.CASE...

    java1.文档中文版

    2. **serialized-form.html**:这个文件详细解释了Java中的序列化机制,包括如何将对象的状态保存到持久化存储,以及如何从存储中恢复这些状态。这对于理解和实现序列化类是至关重要的。 3. **constant-values.html...

    extjs 写的动态加载、增删改查、拖拽Tree (java mysql数据库 已有表结构 eclipse可直接导入)(完整版)

    MySQL数据库则负责存储数据,表结构应与前端展示的数据模型相匹配,以支持正确的数据序列化和反序列化。 Eclipse是Java开发的常用IDE,提供代码编辑、调试和项目管理等功能。提供的项目文件可以直接导入到Eclipse中...

    Tree树结构

    Tree树结构是计算机科学中一种基础且重要的数据结构,它以节点的形式表示数据,并通过边连接这些节点,形成层次化的组织。在树结构中,每个节点都有一个父节点(除了根节点),并且可以有零个或多个子节点。这种结构...

    二叉树、树、森林的java读写操作

    Java中的IO流库可以帮助我们从文件中读取和写入这些序列化的数据。例如,可以使用`FileReader`和`BufferedReader`读取文件,用`FileWriter`和`BufferedWriter`写入文件。同时,`ObjectOutputStream`和`...

    英文语料库词汇标注软件TreeTagger

    4. **命令行界面**:TreeTagger提供命令行接口,用户可以通过编写简单的脚本进行批处理,方便集成到自动化工作流程中。 5. **结果输出**:TreeTagger的输出格式简单明了,易于解析和进一步处理,通常是以空格分隔的...

    java程序员面试题

    Java中的序列化是将对象的状态转换为字节流的过程,以便可以存储或在网络上传输。如果一个类实现了`Serializable`接口,它的实例就可以被序列化。选项C提到的是`Forest`实例被序列化,这可能是因为`Forest`类实现了`...

    OCJP题库JAVA考试

    在题目中,由于`Tree`类没有实现`Serializable`接口,所以在尝试序列化`Forest`实例时,会抛出`java.io.NotSerializableException`。 2. **对象的序列化与反序列化**:在问题2中,正确的序列化和反序列化代码是选项...

    Tree树状菜单

    例如,你可以使用Java的集合框架如`ArrayList`或`LinkedList`来表示树节点,然后通过JSON序列化将树结构传递到前端。Spring Boot框架中的`@RestController`可以方便地处理这种需求。 此外,JavaFX是Java的一个模块...

    SCJP解析系列之一

    本题属于SCJP考试中的一个经典题目,涉及Java对象序列化(Serialization)和IO流的使用。 题目描述了一个尝试将`Forest`类的实例写入到一个名为"Forest.Ser"的文件中的场景。`Forest`类实现了`Serializable`接口,...

Global site tag (gtag.js) - Google Analytics