0

Is there any way to create Map or Set type data structures at compile time?

The reason I ask this is because I'm working with App Engine and I have some data structures that need to be sorted and searched, but they're constant, so I'd like to avoid the time cost of creating them at start-up.

Chris Dutrow
  • 48,402
  • 65
  • 188
  • 258
  • I'm not sure this is possible - how can an object be created before the application runs? If the data is pre-calculated and stored in a flat file (or some other serialization format) you could load it at startup time, but I don't think the compiler can *create* data structure object for you... – FrustratedWithFormsDesigner Nov 02 '10 at 15:33
  • There might not be any available tools to do this, but its possible. For example, its possible to create an array at compile time. If it was sorted, then companion functions could use it as a set. – Chris Dutrow Nov 02 '10 at 15:37
  • @DutrowLLC: could you show an example of creating an array at compile time? – FrustratedWithFormsDesigner Nov 02 '10 at 15:57
  • @FrustratedWithFormsDesigner: public static final int[] intArray = {1,2,3,4,5}; – Chris Dutrow Nov 02 '10 at 21:25
  • @DutrowLLC: Hmmm hadn't thought like that... so even if that array was HUGE there would be no start up cost to create it because it exists at compile time - or something? If there were several million elements, would creating it this way actually be faster? – FrustratedWithFormsDesigner Nov 02 '10 at 23:49
  • @FrustratedWithFormsDesigner - I assume the program would take significantly longer to load in that case. If all the information to create the structure was in your compiled code, then you initialized the data structure on startup, it would probably be slower, since in both cases the compiled code would be bloated up, but in the later you are taking extra time to re-organize the information into a data structure. – Chris Dutrow Nov 02 '10 at 23:58
  • @DutrowLLC: I'd have to try executing a simple test to see if it really makes a difference. Unfortunately, I don't think Java has this ability for Maps or Sets. As far as I know, instances of Map and Set are only initialized at runtime. – FrustratedWithFormsDesigner Nov 03 '10 at 00:15

4 Answers4

3

As with any kind of performance optimization, the first thing to ask yourself is whether the time taken to set up these structures at run time is really affecting performance. How big area your structures? How long do they take to set up? If you haven't measured this you are engaging in premature optimization, which as we know is the root of all evil.

Assuming you have done this, then let's look at the options. How much time can you really save? Your best bet is to use some form of serialization, but you are going to have to write that yourself; even if you define a file format to hold the content, the file is going to have to be parsed, and the in-memory data structures will have to be created. That's going to take time, and it's unlikely to be substantially faster than just creating the Maps or Sets and populating them. In some languages you could theoretically save the bit pattern of the memory for these structures, but even if you can do that you are making yourself vulnerable to any little change in compiler version, and any errors you make will be virtually impossible to debug.

In short, don't do this unless you are sure you need to. Even then, you probably shouldn't do this. The only time you should is if the (probably very small) saving of time will absolutely mean the difference between success and failure of your project.

DJClayworth
  • 26,349
  • 9
  • 53
  • 79
  • Yeah, I wasn't trying to make my life unnessisarily hard, but I didn't know if you could do something like this inside a class ( instead of static{//do stuff} ): compiletime{ //do stuff }; ... now that would be easy... – Chris Dutrow Nov 02 '10 at 22:27
  • It's a reasonable question, but the answer is: it's virtually impossible. – DJClayworth Nov 03 '10 at 13:55
2

If you're using Spring you can create and populate those data structures in configuration and cache them, but I don't see how you can avoid creating and populating them at runtime. You have to run that code sometime. Sounds like pre-mature optimization to me.

duffymo
  • 305,152
  • 44
  • 369
  • 561
1

At compile time I don't think its possible. At run time it is possible. Your best solution is to use the app engine and maybe use the cron job trick to keep it hot cron job link

Then you can define the list in a static block of code which will cache on first run of the application

e.g

private static List<Object> list = new ArrayList<Object>();

static {
    for(Value value : getValues()){
        list.add(value);
    }
}

Also see spring annotations for post construct so you can do the same but in a non static environment by annotating a method with @PostConstruct which will be executed when your object is created.

DeliveryNinja
  • 827
  • 2
  • 12
  • 28
1

No; creation of ALL your objects always happens at runtime.

That being said, you can declare and initialize Sets together like this:

private static Set<String> set = new HashSet<String>(Arrays.asList("abc", "def"));

This will still be executed at runtime though.

To handle Maps, you'd have to use a static initializer instead.

Luke Hutteman
  • 1,921
  • 13
  • 11