如何为程序只填充一次HashMap对象?

How to fill HashMap object only once for 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;
  }
}

我能够在不实例化 AnimalNames class 的情况下访问填充的 animalNameTranslations(使用 static 关键字),这正是我想要的。但是,每次我想访问它时(使用 for 循环),我的程序仍然必须填充 animalNameTranslations。有没有办法只为我的程序填充一次 HashMap 对象?

您可以从静态初始化程序块调用 getAnimalNameTranslations 方法,该方法会在 class 初始化时执行一次。您必须添加一个静态成员来保存该方法返回的 Map。

例如:

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

或者直接将该方法的逻辑移至静态初始化程序块。

  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])
    }
  }

像这样:

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;
      }
}

您可以将您的 animalNameTranslations 声明为私有静态变量,然后更新您的 getAnimalNameTranslations() 方法以初始化 animalNameTranslations ,前提是它之前没有像这样初始化过:

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;
  }
}

这将避免将调用者耦合到 class 中的数据结构,从而封装您的底层实现。

现在需要注意的是,以前每次调用getAnimalNameTranslations()时,你的数据结构都会更新。使用我建议的方法,如果您的 animalNamesanimalNameAbbreviations 发生变化,您将需要单独的方法,例如 addAnimalNameTranslations()deleteAnimalNameTranslations() 等来更新您的基础数据结构。

您可以简单地对地图进行硬编码。当然它是蛮力而且看起来很陈旧,但它速度很快并且在编译时为您构建,永远不需要等待任何代码 运行。如果一切都是静态的并且列表不会改变,那就是一个巨大的胜利。

如果您仍想 运行 一些启动代码,请在静态初始化程序中为程序执行一次。

只需定义一个私有成员并用它填充变量:

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;
  }

您可以使用静态块来解决您的问题。 也称为静态初始化块。 这是一个普通的代码块,用大括号 { } 括起来,前面有 static 关键字。 像这样:

static {
    // add the code for initialization 
}

一个class可以有任意数量的静态初始化块,它们可以出现在class主体的任何地方。 运行时系统保证静态初始化块按照它们在源代码中出现的顺序被调用。

您可以将代码编写为

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])
    }
  }