2

I have a quad tree* which I would like to use across several different machines. Calling the constructor (ie building the tree) takes a long time. I don't want to build the tree each time I need to use it.

I am looking for a way to persist my tree in hard disk, send that to each node, and then quickly load it into memory so that I can perform lookups.

Can serialization help me with this? I know that I can serialize the tree, save it to disk then deserialize (that's about all I know about serialization). To the best of my knowledge, the deserilization step needs a default constructor to build the tree. Since building the tree is computationally expensive, this is of no use to me.

Is there some way I can import the persisted tree without having to rebuild it each time?

*quad tree base code that I used: https://bitbucket.org/utcompling/textgrounder/src/f38150c7f33a/src/main/java/ags/utils/KdTree.java

Apologies if this is too basic, it's closely related to: https://stackoverflow.com/questions/14701245/how-do-i-perform-kd-tree-lookups-in-hadoop

edit: So, it looks like the no-arg constructor of the least-inherited class is the one that will be called. Here's my hirearchy:

abstract KDTree

QuadTree extends KdTree

SpecialQuadTree ( has an instance of QuadTree)

Now, I am only able to serialize SpecialQuadTree when I make everything Serializable (otherwise I'm getting NotSerizable or InvalidClassException no valid constructor):

abstract KDTree implements Serializable

QuadTree extends KdTree implements Serializable

SpecialQuadTree implements Serializable ( has an instance of QuadTree)

So, I suppose I can take the Serializable off the KdTree and then give it a do-nothing no-args constructor? That's not easy, I didn't write and don't understand the KdTree class. I suppose I could subclass it, give the subclass a do-nothing no-args constructor, and inherit the QuadTree from that...

edit: Ok so, I have an abstract class abstract KDTree implements Serializable

and from that I extend: QuadTree extends KdTree implements Serializable

From all my experiments, I need to implement Serializable on both. Now,

public QuadTree() {
    super(2, 1000000);
    System.out.println("QuadTree no-args!");
}

and

protected KdTree(int dimensions, Integer sizeLimit) {
    System.out.println("KdTree, constructor!");

Since I never see it print out (aside from the initial construction...), I guess it's all good.

Community
  • 1
  • 1
dranxo
  • 3,348
  • 4
  • 35
  • 48
  • Do you suppose serializing and deserializing it will be more efficient than using a standardized serialization method, such as XML/JSON? – amphibient Feb 12 '13 at 20:53
  • In the past, I've always used JSON to persist objects. The problem I have now is that I have no idea how to write a method which converts my object into JSON. – dranxo Feb 12 '13 at 20:54
  • I suggest looking at Google Protocol buf – Καrτhικ Feb 12 '13 at 20:55
  • @kabram interesting suggestion. I will look into it. Any more specific hints? – dranxo Feb 12 '13 at 20:56
  • there should be a ton of XML and JSON marshalling (the process you're referring to) to and from JAVA. e.g. JAXB: http://en.wikipedia.org/wiki/JAXB – amphibient Feb 12 '13 at 21:03
  • Well, we are discussing an architectural decision here. If it's a published interface, or one that at least transmits data to foreign components, then JSON is an excellent format. If this data is communicated between components of the same application (just situated on different nodes), then I would stick to Java serialization. – barfuin Feb 12 '13 at 21:07

3 Answers3

3

When an object is deserialized in Java, only some of the no-args constructors are called (see this post).

The easiest way is to make all involved classes Serializable. Then none of your constructors will be called. If you cannot do that, make sure that your Serializable classes have access to the no-args constructor of the first non-Serializable class.

In case of a non-Serializable base class which is under your control, you could move your expensive logic to a different constructor (let's say, with a dummy boolean argument) and provide a simple no-args constructor that does nothing. Then all your fields will be there after deserialization without the computation overhead.

The ultimate source of information is the the serialization spec.

Community
  • 1
  • 1
barfuin
  • 16,865
  • 10
  • 85
  • 132
2

To the best of my knowledge, the deserilization step needs a default constructor to build the tree

Not if you're taking about Java Object Serialization it doesn't.

it looks like the no-arg constructor of the least-inherited class is the one that will be called.

No. The no-args constructor of the nearest non-serializable base class is called.

I suppose I can take the Serializable off the KdTree and then give it a do-nothing no-args constructor?

Why? Just leave it alone.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • ok. I'm new at this, is it really just "implements Serializable" on all my classes and then Java figures it out? – dranxo Feb 12 '13 at 20:58
  • 2
    The default constructor of the most derived non-`Serializable` class will be called (different rules for `Externalizable`, but that's different odd). – Tom Hawtin - tackline Feb 12 '13 at 21:01
  • Note that a "default constructor" is a *no-args* constructor that Java creates for you if your class defines no constructors. So we are probably talking *no-args* constructors, not default constructors. – barfuin Feb 12 '13 at 21:02
  • @rcompton Control what? If your class is Serializable, *none* of its constructors will get called during de-serialization. – user207421 Feb 12 '13 at 22:01
  • @EJP I was unclear "The default constructor of the most derived non-Serializable class will be called" is what I'm trying to figure out. – dranxo Feb 12 '13 at 22:04
  • @rcompton See my edit. If KdTree is Serializable its constructors aren't called. – user207421 Feb 12 '13 at 22:06
  • ok then, so, I'll make everything Serializable then. Then no constructors will ever be called. Probably not the proper way to do this, but seems ok with me. – dranxo Feb 12 '13 at 22:08
  • @rcompton At a minimum, Object() will be called. I don't know why you think this mightn't be the right way. It's the right way if everything you want serialized is serialized. – user207421 Feb 12 '13 at 22:09
  • @EJP re: "Why? Just leave it alone." ok, I made everything Serializable. Put system.outs all over the place. Looks like my constructor does not get called during the Serialization/DeSerilzation process. – dranxo Feb 12 '13 at 22:27
  • @rcompton Yes, that's what the Object Serialization Specification says. – user207421 Feb 16 '13 at 11:10
0

If you are using Jackson, How about having a custom deserializer and attach to class where you are trying to deserialize ?