danger mouse
danger mouse

Reputation: 1497

How to fill HashMap object only once for program?

Given the following portion of my wider program:

public class AnimalNames {
  private static String[] animalNames = {dog, cat, horse, cow, donkey, elephant};
  private static String[] animalNameAbbreviations = {d, c, h, co, d, e};
  public static HashMap<String, String> getAnimalNameTranslations() {
    HashMap<String, String> animalNameTranslations = new HashMap<String, String>();
    for (int i = 0; i < animalNames.length; i++) {
      animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
    }
    return animalNameTranslations;
  }
}

I'm able to access the filled animalNameTranslations (using the static keyword) without instantiating the AnimalNames class, which is what I want. However, my program still has to fill animalNameTranslations every time I want to access it (using the for loop). Is there a way to fill the HashMap object only once for my program?

Upvotes: 4

Views: 2600

Answers (6)

Abhijit Bashetti
Abhijit Bashetti

Reputation: 8658

You can use the static blocks to resolve your problem. Also called Static initialization blocks . This is a normal block of code enclosed in braces, { }, and preceded by the static keyword. like this :

static {
    // add the code for initialization 
}

A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.

you can write your code as

private static HashMap<String, String> animalNameTranslations;
  static {
    animalNameTranslations = new HashMap<String, String>();
    for (int i = 0; i < animalNames.length; i++) {
      animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
    }
  }

Upvotes: 1

ivan.sim
ivan.sim

Reputation: 9268

You can declare your animalNameTranslations as a private static variable, and then update your getAnimalNameTranslations() method to initialize animalNameTranslations only if it hasn't been previously initialize like this:

public class AnimalNames {
  private static HashMap<String, String> animalNameTranslations;
  public static HashMap<String, String> getAnimalNameTranslations() {
    if(animalNameTranslations == null) {
      animalNameTranslations = new HashMap<String, String>();
      for (int i = 0; i < animalNames.length; i++)
        animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
    }
    return animalNameTranslations;
  }
}

This will avoid coupling your callers to a data structure in your class, encapsulating your underlying implementation.

Now something to pay attention to is that previously, your data structure will be updated every time getAnimalNameTranslations() is called. With my suggested approach, if your animalNames and animalNameAbbreviations ever changed, you will need separate methods like, addAnimalNameTranslations(), deleteAnimalNameTranslations() etc. to update your underlying data structure.

Upvotes: 3

Siamak Ferdos
Siamak Ferdos

Reputation: 3299

Simply define a private member and fill variable by it:

private static HashMap<String, String> _animalNameTranslations = new HashMap<String, String>();
public static HashMap<String, String> getAnimalNameTranslations() {
    var animalNameTranslations = _animalNameTranslations;
    for (int i = 0; i < animalNames.length; i++) {
      animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
    }
    return animalNameTranslations;
  }

Upvotes: 0

The Software Barbarian
The Software Barbarian

Reputation: 459

You can simply hardcode the map. Sure it's brute force and it seems archaic, but it's fast and built for you at compile time, no waiting for any code to run ever. If everything's static anyway and the list won't be changing, it's a huge win.

If you still want to run some startup code, do it in a static initializer, once for the program.

Upvotes: 0

Sergey Maksimenko
Sergey Maksimenko

Reputation: 588

Like this:

public class AnimalNames {
      private static String[] animalNames = {dog, cat, horse, cow, donkey, elephant};
      private static String[] animalNameAbbreviations = {d, c, h, co, d, e};
      private static HashMap<String, String> animalNameTranslations = new HashMap<String, String>();
      static{
         for (int i = 0; i < animalNames.length; i++) {
          animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
         }
      }
      public static HashMap<String, String> getAnimalNameTranslations() {
        return animalNameTranslations;
      }
}

Upvotes: 1

Eran
Eran

Reputation: 393801

You can call the getAnimalNameTranslations method from your static initializer block, which would be executed once, when the class is initialized. You'll have to add a static member that holds the Map returned by the method.

For example :

private static HashMap<String, String> animalNameTranslations;
static {
    animalNameTranslations = getAnimalNameTranslations ();
}

Or just move the logic of that method directly to the static initializer block.

  private static HashMap<String, String> animalNameTranslations;
  static {
    animalNameTranslations = new HashMap<String, String>();
    for (int i = 0; i < animalNames.length; i++) {
      animalNameTranslations.put(animalNameAbbreviations[i], animalNames[i])
    }
  }

Upvotes: 4

Related Questions