Reputation: 1497
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
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
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
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
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
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
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