在Scala/Java中有没有类似Python Pickle的简单无麻烦的零样板序列化?

37 投票
5 回答
8787 浏览
提问于 2025-04-17 03:18

有没有一种简单方便的方法可以在Scala或Java中进行序列化,类似于Python的pickle?pickle是一个非常简单的解决方案,效率还不错(也不是特别差),但它不考虑跨语言的兼容性、版本控制等问题,并且允许一些自定义。

我了解到的情况有:

Kryo和protostuff是我找到的最接近的解决方案,但我想知道是否还有其他的选择(或者有没有什么使用这些库的方法是我应该知道的)。请提供一些使用示例!最好也能包括一些性能对比。

5 个回答

7

Twitter的chill库真是太棒了。它使用Kryo来进行数据的序列化,但使用起来非常简单。另外,它还提供了一种叫做MeatLocker[X]的类型,可以让任何类型X都变得可以序列化。

11

我觉得你最好使用kryo(我不知道还有其他不需要定义太多结构的替代方案,除了非二进制协议)。你提到pickle在没有注册类的情况下不会像kryo那样变慢或变得臃肿,但其实kryo即使不注册类,速度还是比pickle快,而且占用空间也更小。下面是一个简单的对比测试(当然,这只是我能轻松做的,结果仅供参考):

Python的pickle

import pickle
import time
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
people = [Person("Alex", 20), Person("Barbara", 25), Person("Charles", 30), Person("David", 35), Person("Emily", 40)]
for i in xrange(10000):
    output = pickle.dumps(people, -1)
    if i == 0: print len(output)
start_time = time.time()
for i in xrange(10000):
    output = pickle.dumps(people, -1)
print time.time() - start_time    

在我这边输出174字节,耗时1.18到1.23秒(在64位Linux上使用Python 2.7.1)。

Scala的kryo

import com.esotericsoftware.kryo._
import java.io._
class Person(val name: String, val age: Int)
object MyApp extends App {
  val people = Array(new Person("Alex", 20), new Person("Barbara", 25), new Person("Charles", 30), new Person("David", 35), new Person("Emily", 40))
  val kryo = new Kryo
  kryo.setRegistrationOptional(true)
  val buffer = new ObjectBuffer(kryo)
  for (i <- 0 until 10000) {
    val output = new ByteArrayOutputStream
    buffer.writeObject(output, people)
    if (i == 0) println(output.size)
  }
  val startTime = System.nanoTime
  for (i <- 0 until 10000) {
    val output = new ByteArrayOutputStream
    buffer.writeObject(output, people)
  }
  println((System.nanoTime - startTime) / 1e9)
}

在我这边输出68字节,耗时30到40毫秒(使用Kryo 1.04,Scala 2.9.1,Java 1.6.0.26的热点JVM在64位Linux上)。如果我注册类,输出会是51字节,耗时18到25毫秒。

对比

不注册类时,kryo的空间占用大约是Python pickle的40%,耗时大约是3%。注册类后,kryo的空间占用大约是30%,耗时大约是2%。而且你总是可以写一个自定义的序列化器,以便获得更多的控制权。

9

编辑于2020年2月19日:请注意,正如下面的@federico提到的,这个回答已经不再有效,因为这个仓库已经被所有者归档了。

现在,Scala有了Scala-pickling,在某些情况下,它的表现和Kyro一样好,甚至更好——可以查看这个演示文稿的第34到39页。

撰写回答