Scala 系列化番石榴';s MinMaxPriorityQueue
经过几天的研究,我得出结论,问题出在我使用的Scala 系列化番石榴';s MinMaxPriorityQueue,scala,guava,apache-flink,kryo,Scala,Guava,Apache Flink,Kryo,经过几天的研究,我得出结论,问题出在我使用的MinMaxPriorityQueue中 似乎此结构不可序列化。我尝试了几种序列化方法: env.getConfig.registerTypeWithKryoSerializer(classOf[MinMaxPriorityQueue[Double]], classOf[JavaSerializer]) env.getConfig.registerTypeWithKryoSerializer(classOf[MinMaxPriorityQueue[ja
MinMaxPriorityQueue
中
似乎此结构不可序列化。我尝试了几种序列化方法:
env.getConfig.registerTypeWithKryoSerializer(classOf[MinMaxPriorityQueue[Double]], classOf[JavaSerializer])
env.getConfig.registerTypeWithKryoSerializer(classOf[MinMaxPriorityQueue[java.lang.Double]], classOf[ProtobufSerializer]);
env.getConfig().addDefaultKryoSerializer(MyCustomType.class, TBaseSerializer.class);
他们都不走运
但我发现:
是否有与MinMaxPriorityQueue等效的方法,或序列化它的方法
使现代化
我已将Tomasz翻译成scala:
class MinMaxPriorityQueueSerializer extends Serializer[MinMaxPriorityQueue[Object]] {
private[this] val log = LoggerFactory.getLogger(this.getClass)
setImmutable(false)
setAcceptsNull(false)
val OPTIMIZE_POSITIVE = true
override def read(kryo: Kryo, input: Input, aClass: Class[MinMaxPriorityQueue[Object]]): MinMaxPriorityQueue[Object] = {
log.error("Kryo READ")
val comparator: Ordering[Object] = kryo.readClassAndObject(input).asInstanceOf[Ordering[Object]]
val size = input.readInt(OPTIMIZE_POSITIVE)
val queue: MinMaxPriorityQueue[Object] = MinMaxPriorityQueue.orderedBy(comparator)
.expectedSize(size)
.create()
(0 to size).foreach(_ => queue.offer(kryo.readClassAndObject(input)))
queue
}
override def write(kryo: Kryo, output: Output, queue: MinMaxPriorityQueue[Object]): Unit = {
log.error("Kryo WRITE")
kryo.writeClassAndObject(output, queue.comparator)
val declaredSize = queue.size
output.writeInt(declaredSize, OPTIMIZE_POSITIVE)
val actualSize = queue.toArray.foldLeft(0) {
case (z, q) =>
kryo.writeClassAndObject(output, q)
z + 1
}
Preconditions.checkState(
declaredSize == actualSize,
"Declared size (%s) different than actual size (%s)", declaredSize, actualSize)
}
}
并在flink中设置kryo以使用该序列化程序:
env.getConfig.addDefaultKryoSerializer(classOf[MinMaxPriorityQueue[Double]], classOf[MinMaxPriorityQueueSerializer])
env.getConfig.registerTypeWithKryoSerializer(classOf[MinMaxPriorityQueue[Double]], classOf[MinMaxPriorityQueueSerializer])
然而,它似乎从未被调用,因为我在日志中的任何地方都没有看到log.error(“Kryo READ”)
和log.error(“Kryo WRITE”)
转换仍然返回一个空的MinMaxPriorityQueue,即使我正在更新它
更新2
我已经实现了SerializerTester,但是我得到了一个缓冲区下溢:
object Main {
def main(args: Array[String]) {
val tester = new MinMaxPriorityQueueSerializerTester()
val inQueue: MinMaxPriorityQueue[java.lang.Double] = MinMaxPriorityQueue.create()
inQueue.add(1.0)
val outputStream = new ByteArrayOutputStream()
tester.serialize(outputStream, inQueue)
val inputStream = new ByteArrayInputStream(outputStream.toByteArray())
val outQueue: MinMaxPriorityQueue[java.lang.Double] = tester.deserialize(inputStream);
System.out.println(inQueue);
System.out.println(outQueue);
}
class MinMaxPriorityQueueSerializerTester {
val kryo = new Kryo
kryo.setInstantiatorStrategy(new StdInstantiatorStrategy)
registerMinMaxSerializer();
// allowForClassesWithoutNoArgConstructor(); // needed to serialize Ordering
def registerMinMaxSerializer() {
kryo.addDefaultSerializer(classOf[MinMaxPriorityQueue[java.lang.Double]], new MinMaxPriorityQueueSerializer());
}
def serialize(out: OutputStream, queue: MinMaxPriorityQueue[java.lang.Double]) {
// try (Output output = new Output(out)) {
val output = new Output(out)
kryo.writeClassAndObject(output, queue)
// kryo.writeObject(output, queue)
//}
output.flush
}
def deserialize(in: InputStream): MinMaxPriorityQueue[java.lang.Double] = {
//try (Input input = new Input(in)) {
val input = new Input(in)
//kryo.readObject(input, classOf[MinMaxPriorityQueue[java.lang.Double]])
kryo.readClassAndObject(input).asInstanceOf[MinMaxPriorityQueue[java.lang.Double]]
//p}
}
}
您可以使用自定义Kryo
序列化程序
下面是一个示例(Java):
类MinMaxPriorityQueueSerializer扩展了序列化程序{
私有静态最终布尔优化_正=真;
受保护的MinMaxPriorityQueueSerializer(){
SetAcceptsAll(假);
设置不可变(false);
}
@凌驾
公共无效写入(Kryo Kryo、输出、MinMaxPriorityQueue队列){
writeClassAndObject(输出,queue.comparator());
int declaredSize=queue.size();
output.writeInt(declaredSize,优化_正数);
int-actualSize=0;
for(对象元素:队列){
writeClassAndObject(输出,元素);
actualSize++;
}
先决条件(
declaredSize==实际大小,
“声明的大小(%s)与实际大小(%s)不同”,declaredSize,actualSize
);
}
@凌驾
公共MinMaxPriorityQueue读取(Kryo Kryo,输入,类类型){
@抑制警告(“未选中”)
比较器比较器=(比较器)kryo.readClassAndObject(输入);
int size=input.readInt(正优化);
MinMaxPriorityQueue=MinMaxPriorityQueue.orderedBy(比较器)
.预期尺寸(尺寸)
.create();
对于(int i=0;i
以下是您可以如何使用它:
class MinMaxPriorityQueueSerializerTester {
public static void main(String[] args) {
MinMaxPriorityQueueSerializerTester tester = new MinMaxPriorityQueueSerializerTester();
MinMaxPriorityQueue<Integer> inQueue = MinMaxPriorityQueue.<Integer>orderedBy(Comparator.reverseOrder())
.create(Arrays.asList(5, 2, 7, 2, 4));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
tester.serialize(outputStream, inQueue);
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
@SuppressWarnings("unchecked")
MinMaxPriorityQueue<Integer> outQueue = (MinMaxPriorityQueue<Integer>) tester.deserialize(inputStream);
System.out.println(inQueue);
System.out.println(outQueue);
}
private final Kryo kryo;
public MinMaxPriorityQueueSerializerTester() {
this.kryo = new Kryo();
registerMinMaxSerializer();
allowForClassesWithoutNoArgConstructor(); // needed to serialize Ordering
}
private void registerMinMaxSerializer() {
kryo.addDefaultSerializer(MinMaxPriorityQueue.class, new MinMaxPriorityQueueSerializer());
}
private void allowForClassesWithoutNoArgConstructor() {
((Kryo.DefaultInstantiatorStrategy) kryo.getInstantiatorStrategy())
.setFallbackInstantiatorStrategy(new StdInstantiatorStrategy());
}
public void serialize(OutputStream out, MinMaxPriorityQueue<?> queue) {
try (Output output = new Output(out)) {
kryo.writeObject(output, queue);
}
}
public MinMaxPriorityQueue<?> deserialize(InputStream in) {
try (Input input = new Input(in)) {
return kryo.readObject(input, MinMaxPriorityQueue.class);
}
}
}
class MinMaxPriorityQueueSerializerTester{
公共静态void main(字符串[]args){
MinMaxPriorityQueueSerializerTester=新的MinMaxPriorityQueueSerializerTester();
MinMaxPriorityQueue inQueue=MinMaxPriorityQueue.orderedBy(Comparator.reverseOrder())
.create(Arrays.asList(5,2,7,2,4));
ByteArrayOutputStream outputStream=新建ByteArrayOutputStream();
序列化(outputStream,inQueue);
ByteArrayInputStream inputStream=新建ByteArrayInputStream(outputStream.toByteArray());
@抑制警告(“未选中”)
MinMaxPriorityQueue outQueue=(MinMaxPriorityQueue)测试器。反序列化(inputStream);
System.out.println(inQueue);
System.out.println(输出队列);
}
私人决赛高雄高雄;
public MinMaxPriorityQueueSerializerTester(){
this.kryo=新的kryo();
registerMinMaxSerializer();
allowForClassesWithoutNoArgConstructor();//序列化排序需要
}
专用无效注册表项MaxSerializer(){
addDefaultSerializer(MinMaxPriorityQueue.class,新的MinMaxPriorityQueueSerializer());
}
私有void allowforclassswithoutnoargconstructor(){
((Kryo.defaultInstanceorStrategy)Kryo.getInstanceorStrategy())
.SetFallbackInstanceorStrategy(新StdInstantiatorStrategy());
}
public void序列化(OutputStream out,MinMaxPriorityQueue){
尝试(输出=新输出(输出)){
writeObject(输出,队列);
}
}
public MinMaxPriorityQueue反序列化(InputStream in){
尝试(输入=新输入(输入)){
返回kryo.readObject(输入,MinMaxPriorityQueue.class);
}
}
}
我最终放弃了,尝试使用不同的数据结构,并使用java.io.Serializable
将其序列化
这个数据结构是一个,我刚刚在中使它可以序列化
现在一切正常。您可以在Guava的Github repo中创建一个问题并请求该功能。有,其中提到了
MinMaxPriorityQueue
,但最后它没有包含在票据的范围内。@Xaerxess,谢谢,我已经打开了它:@elbaulp你能发布bufferUnderflow的堆栈跟踪吗?没关系,我改为使用intervalHeap的这个实现:因为它是开箱即用的。谢谢你的帮助,我接受你的回答。@elbaulp谢谢,尽管我的回答并没有真正解决你的问题。你可能会考虑单独回答一个问题,如果其他人有类似的问题,你会如何解决它。谢谢,我已经尝试过了,运气不好:-(@ El Baulp我用java测试了这个代码代码,它工作了。你测试过斯卡拉(Flink以外)的序列化吗?如果没有,请做。(正如我在MinMaxPriorityQueueSerializerTester
中所做的),然后我们将了解更多。
class MinMaxPriorityQueueSerializerTester {
public static void main(String[] args) {
MinMaxPriorityQueueSerializerTester tester = new MinMaxPriorityQueueSerializerTester();
MinMaxPriorityQueue<Integer> inQueue = MinMaxPriorityQueue.<Integer>orderedBy(Comparator.reverseOrder())
.create(Arrays.asList(5, 2, 7, 2, 4));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
tester.serialize(outputStream, inQueue);
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
@SuppressWarnings("unchecked")
MinMaxPriorityQueue<Integer> outQueue = (MinMaxPriorityQueue<Integer>) tester.deserialize(inputStream);
System.out.println(inQueue);
System.out.println(outQueue);
}
private final Kryo kryo;
public MinMaxPriorityQueueSerializerTester() {
this.kryo = new Kryo();
registerMinMaxSerializer();
allowForClassesWithoutNoArgConstructor(); // needed to serialize Ordering
}
private void registerMinMaxSerializer() {
kryo.addDefaultSerializer(MinMaxPriorityQueue.class, new MinMaxPriorityQueueSerializer());
}
private void allowForClassesWithoutNoArgConstructor() {
((Kryo.DefaultInstantiatorStrategy) kryo.getInstantiatorStrategy())
.setFallbackInstantiatorStrategy(new StdInstantiatorStrategy());
}
public void serialize(OutputStream out, MinMaxPriorityQueue<?> queue) {
try (Output output = new Output(out)) {
kryo.writeObject(output, queue);
}
}
public MinMaxPriorityQueue<?> deserialize(InputStream in) {
try (Input input = new Input(in)) {
return kryo.readObject(input, MinMaxPriorityQueue.class);
}
}
}