Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build a complex, hierarchic immutable data structure in Java?

Tags:

java

I'm building a Java library for a customer, and one of the things they want is a data representation of a particular set of standards they work with. I don't want to reveal my customer's interests, but if he were an alchemist, he might want the following:

Elements
  Fire
    Name="Fire"
    Physical
      Temperature=451
      Color="Orange"
    Magical
      Domain="Strength"
  Water
    Name="Water"
    Physical
      Color="Blue"
  Earth
    Name="Earth"
    Magical
      Domain="Stability"
      Ordinality=1

I need to be able to access various data elements by name, such as:

  Elements.Earth.Name
  Elements.Water.Physical.Color

I also need to be able to iterate through attributes, as:

  for (MagicalType attrib : Elements.Fire.Magical)
  {
    ...
  }

I have actually been able to create this data structure, and I can do everything I've asked for above -- though I had to create separate arrays for the iteration, so really what I do looks more like:

  for (MagicalType attrib : Elements.Fire.MagicalAuxArray)

Unfortunately I haven't been able to meet my last requirement: the entire data structure must be immutable. I have tried repeatedly, and scoured the web looking for examples, but so far I haven't been able to accomplish this in any reasonable manner. Note that the final data structure will be quite large; I'm really hoping to avoid a solution that is too repetitious or creates too many public symbols.

I am a very experienced programmer, less experienced with Java. Can anyone suggest how I might represent the above data to meet all my requirements?

like image 657
vw-register Avatar asked Sep 18 '10 18:09

vw-register


1 Answers

A few ways that come to mind immediately:

  • Don't provide setter methods for your object. You users can only create the object via a constructor and once created, it cannot be modified. This goes for other state-modification methods as well. If you want to avoid a very large parameter-list in your constructor, you can use the Builder pattern (described in Effective Java by Joshua Bloch (2nd Ed))
  • When returning collections, make defensive copies. In this case use a List instead of an array. That way you can do return new ArrayList<MagicalType>(MagicalAuxList) instead of return MagicalAuxList. This way people who use the class won't be able to modify the collection. One caveat here. If your array contains complex objects, they must be immutable as well.
  • For immutable collections, you can also try using the unmodifiableCollection static method (there are similar static-methods for lists, sets, etc. - use whichever one is appropriate for you) to convert your collection when you return it. This is an alternative to defensive copying.
like image 144
Vivin Paliath Avatar answered Oct 27 '22 00:10

Vivin Paliath