Question

I have a class called Location which has 2 type of information, one is a nodeID (a integer) and another is diskPosition (a long). My application needs to create many objects of this Location class but most of the time I will assign a default value (say -1) to one of these two variable inside the class Location.

My question is "should I declare these nodeID and diskPosition as Integer and Long and assign default value null instead of keeping them as primitive and assigning default value as -1)"

My concern is amount of memory being taken by my Location object and I want to minimize it.

Below is code snippet of Location class:

public class Location
{
    private int     nodeID  = -1;
    private long    diskPos = -1;

    public Location(long diskPos)
    {
        this.diskPos = diskPos;
    }

    public Location(Node node)
    {
        this.nodeID = node.getNodeID();
    }

    // Test main method to elaborate usage of Location object
    public void main(String[] args)
    {
        Map<Integer, Location> cellIDToLocationMap = new HashMap<Integer, Location>();

        // Consider there is a list of nodes which is obtained from somewhere
        List<Node> nodeList = getNodeList();

        Location loc = null;
        for (int i = 1; i <= 10000; i++)
        {
            if (i % 2 == 0)
                loc = new Location(nodeList.get(i));
            else
                loc = new Location(i);

            // Put in map
            cellIDToLocationMap.put(i, loc);
        }
    }
}
Was it helpful?

Solution

The answer depends on how many instances you create and on the distribution of the nodeID and diskPos values. Let's look at the numbers, assuming a 32-bit JVM (or 64-bit with pointer compression). The values might still not match your JVM implementation, but they should be correct for HotSpot.

With int and long a Location instance takes 24 bytes. With Integer and Long, it depends. The Location instances takes 16 bytes, and the Integer and Long objects might take 16 each, unless they are shared. If, as you say, one of them stays -1 (or null) most of the time, that takes no memory, so that makes either 16 or 32 bytes total. Whether Integer or Long instances are shared depends on the value and the JVM settings. As diskPos needs to be long, it's quite unlikely the the instances would be cached.

So the answer is: primitive = 24 bytes, boxed very likely 32 bytes. Stay with the primitives.

You could get memory consumption down to 16 bytes per instance if you use different classes implementing a common interface. I would not do this for the memory savings (you'd need millions of instances before you even notice), but for more readable code, since, with one of the field -1, Location is effectively a union type, and you probably have code like this:

if (location.getNodeId() >= 0) {
    // do something with node id
} else {
    // do something with diskPos
}

A more object oriented design would let you incorporate the different behavior into the respective classes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top