在java中将大量对象存储到磁盘的最佳方法

NEO*_*NEO 5 java serialization

这是我计划存储在磁盘中的对象,

public class SObject {
    /**
     * 
     */
    private String value;
    private int occurences;
    private String key;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public int getOccurences() {
        return occurences;
    }

    public void setOccurences(int occurences) {
        this.occurences = occurences;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在考虑创建一个对象列表并将该列表存储到一个新类中,如下所示,

public class ToDisk implements Serializable{
        List<SObject> sobj;

    public List<SObject> getSobj() {
        return sobj;
    }

    public void setSobj(List<SObject> sobj) {
        this.sobj = sobj;
    }

}
Run Code Online (Sandbox Code Playgroud)

这是一种以最少的代码工作来写入数据的有效方法吗?我还发现使用序列化从磁盘读取数据更容易。因为列表的大小可能非常大(~10k+),我应该在代码的易用性和大小之间找到平衡。有什么办法可以达到这种平衡吗?请告诉我是否有任何其他方法可以比序列化更小地存储数据。我无法使用任何外部库。

Pet*_*rey 6

顺便说一句,您不需要列表包装​​器即可将许多项目写入文件,但您的项目需要可序列化。

public class SObject {
    private String value;
    private int occurences;
    private String key;
}
Run Code Online (Sandbox Code Playgroud)

来写

List<SObject> list = new ArrayList<>();

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fileName));
oos.writeObject(list);
oos.close();
Run Code Online (Sandbox Code Playgroud)

读书

ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName));
List<SObject> list = (List<SObject>) ois.readObject(); // cast is needed.
ois.close()
Run Code Online (Sandbox Code Playgroud)

写压缩的

ObjectOutputStream oos = new ObjectOutputStream(new DeflaterOutputStream(new FileOutputStream(fileName)));
oos.writeObject(list);
oos.close();
Run Code Online (Sandbox Code Playgroud)

读取压缩的

ObjectInputStream ois = new ObjectInputStream(new InflaterInputStream(new FileInputStream(fileName)));
List<SObject> list = (List<SObject>) ois.readObject(); // cast is needed.
ois.close()
Run Code Online (Sandbox Code Playgroud)

这是一种以最少的代码工作来写入数据的有效方法吗?

您必须创建 SObject implement Serializable,仅此而已。你不能让它变得更短。

你可以通过制作来提高它的效率implement Externalizable,但这需要更多的工作。

我还发现使用序列化从磁盘读取数据更容易。

听起来这是一个很好的理由。

因为列表的大小可能非常大(~10k+),

10K 对我来说听起来很小,除非你的琴弦真的很长。我对我的序列化/持久性库进行了测试,它在几秒钟内写入和读取 10,000,000 个条目。

我应该在代码的易用性和大小之间找到平衡。有什么办法可以达到这种平衡吗?

我怀疑你所需要担心的就是安逸。如果您想让文件变得更小,您可以通过使用 GZIP 或 deflator/inflator 流包装文件流来压缩它。这会添加一行代码,并且可以使文件缩小 4 倍。

请告诉我是否有任何其他方法可以比序列化更小地存储数据。我无法使用任何外部库。

它们都需要外部库。您可以使用 XMLEncoder 和 XMLDecoder,但这会更慢且更大。


因为我有一个关于它的问题;如果您对我的库Java Chronicle 2.x感兴趣,这里是在我的笔记本电脑上运行的测试结果。这次写入 5 亿个条目并在第二个线程中读取它们(当它们被写入时)需要多长时间 只花了 12 秒多一点。

Rate = 41.0 Mmsg/sec for 16 byte messages
Run Code Online (Sandbox Code Playgroud)

测试是IndexedChronicleTest中的 multiThreaded()

  • @Jitendra 这是 Java Chronicle,我的测试显示在笔记本电脑上每秒写入 4000 万条消息,并且在另一个进程中读取消息,延迟为 0.6 微秒。https://github.com/peter-lawrey/Java-Chronicle 是旧版本,https://github.com/OpenHFT/Java-Chronicle 是更快、新的改进版本。 (2认同)