Java 间隔树实现在序列化后占用大量文件空间
我有一个包含IPv6范围和范围所属ISP的文本文件(范围不重叠)。以下是一些示例(假)行:Java 间隔树实现在序列化后占用大量文件空间,java,algorithm,optimization,serialization,tree,Java,Algorithm,Optimization,Serialization,Tree,我有一个包含IPv6范围和范围所属ISP的文本文件(范围不重叠)。以下是一些示例(假)行: 2010:258:0:0:0:0:0:0;2010:258:ffff:ffff:ffff:ffff:ffff:ffff;ISP_1; 2010:260:0:0:0:0:0:0;2010:260:ffff:ffff:ffff:ffff:ffff:ffff;ISP_2; 2010:268:0:0:0:0:0:0;2010:268:ffff:ffff:ffff:ffff:ffff:ffff;ISP_3; 我已
2010:258:0:0:0:0:0:0;2010:258:ffff:ffff:ffff:ffff:ffff:ffff;ISP_1;
2010:260:0:0:0:0:0:0;2010:260:ffff:ffff:ffff:ffff:ffff:ffff;ISP_2;
2010:268:0:0:0:0:0:0;2010:268:ffff:ffff:ffff:ffff:ffff:ffff;ISP_3;
我已经取得了这个文本文件,并创建了一个从它,所以我可以快速查找哪个ISP的一个特定的IP属于。间隔树中的每个节点都具有以下结构:
public class Node implements Serializable {
Range nodeRange;
IntervalTreeNode left;
IntervalTreeNode right;
UnsignedLong128 centerValue;
}
以下是范围
:
public abstract class Range implements Comparable<Range>, Serializable {
UnsignedLong128 start;
UnsignedLong128 end;
boolean sortAccordingToStart;
}
问题是,如果我序列化树并将其写入文件,该文件的大小远远大于原始文本文件的大小。下面是一个示例:我有一个文本文件,其中包含19860行范围行,该文本文件的大小为1.7MB。当我基于它创建间隔树并将该树写入文件时(通过Java的序列化),结果文件的大小为15.7 MB,即使它存储相同的信息。是的,树所容纳的节点数量是文本文件行数的两倍(我生成的树是平衡的),这仍然不能证明文件大小增加了这么多
那么,是什么导致了文件大小的增长,我该如何缩减它呢?Java序列化将有很大的开销,如果您使用文本编辑器查看文件,您可能会看到这一点 由于这些范围不重叠,您可以将数据按顺序排序(比较两个范围并比较其起点或终点),然后使用二进制搜索查找匹配项。然后你只需要序列化一个结构数组。您可能会发现,如果您有一个或三个大数组,其中包含起点、终点和ISP ID,或者您可以自己读取和写入数据,那么Java序列化的开销会更小
您还可以研究readResolve()和writeReplace()您可以实现
Externalizable
,它允许您在使用Serializable
框架的同时自定义序列化。它相当简单,每个字段和每个方向都需要一条线Serializable
有一些开销,因为每个字段都可能包含null
或其类型的子类的实例,但您通常知道这是不可能发生的
我不确定,但我想,Serializable
默认情况下使用UTF-16,这既快又简单,因为这是Java内部的功能(或者说,Java 9可以做得更好),但对于纯ASCII来说,它浪费了两倍的时间(使用UTF-8很好)。看起来你用数字代替了字符串,所以可能没用
您的
UnsignedLong128
也会浪费内存。将Long
替换为Long
。不知道它对序列化的数据大小有多大帮助,但可以节省大量RAM(并获得一些速度)。如果不需要坚持序列化,还可以创建readFile
和toFile
方法来存储树。
public class UnsignedLong128 implements Comparable<UnsignedLong128>, Serializable {
Long major;
Long minor;
}