Java - 如何通过值在方法内部初始化一个 HashMap

Java - how to initialize a HashMap inside method by value

我是 Java 的新手,我尝试了几种方法来通过方法初始化我的 HashMap,但是每次执行方法后,我的 Map 仍然是空的,我可以在 LoadData方法执行,我的maps是从子方法赋值的,但是跳出LoadData的时候,我的外参又变成空Map了

// file1.java
public Map<String, Student> getStudentWithIdMap() { ... }
public Map<String, Teacher> getTeacherWithIdMap() { ... }

public static void LoadData(Map<String, Student> studentMap, Map<String, Teacher> teacherMap, ...other Map)
{
     studentMap = getStudentWithIdMap();
     //I tried with studentMap.putAll(getStudentWithIdMap());
     // doing this triggers an exception like "UnsupportedOperationException"
     // I also tried studentMap = new HashMap<>(getStudentWithIdMap());
     teacherMap = getTeacherWithIdMap();
}

// file2.java
public void PrepareData() {
   Map<String, Student> studentMap = Collections.emptyMap();
   Map<String, Teacher> teacherMap = Collections.emptyMap();
   file1.LoadData(studentMap, teacherMap, ...);
}

处理上述情况的原因和最佳方法是什么?

我了解到 Java 始终将方法视为值类型,因此如果传递 class 对象并修改其值,它会在方法完成执行后被修改,为什么 Map 的行为不同?

如果你这样做

 studentMap = getStudentWithIdMap();

变量studentMap将通过getStudentwithIdMap();指向Map return,不影响PrepareData中变量studentMap引用的Map方法。

要实际更改 Map 您需要将值插入其中。

例如:

public static void LoadData(Map<String, Student> studentMap, Map<String, Teacher> teacherMap, ...other Map)
{
     studentMap.putAll( getStudentWithIdMap() );
     //I tried with studentMap.putAll(getStudentWithIdMap());
     // doing this triggers an exception like "UnsupportedOperationException"
     // I also tried studentMap = new HashMap<>(getStudentWithIdMap());
     teacherMap.putAll( getTeacherWithIdMap() );
}

这将导致另一个问题,因为您使用 Collection.emptyMap() 初始化了这些变量。您不能更改该映射,因此写入将失败。

这可以通过以下方法解决:

public void PrepareData() {
   Map<String, Student> studentMap = new HashMap<>();
   Map<String, Teacher> teacherMap = new HashMap<>();
   file1.LoadData(studentMap, teacherMap, ...);
}

你的代码对我来说意义不大:

public static void LoadData(Map<String, Student> studentMap, 
                            Map<String, Teacher> teacherMap, ...other Map) {
    studentMap = getStudentWithIdMap();

那个赋值就是给一个参数赋值。这是一个参考任务。它不会影响作为参数传递的地图。

<Emphasis> Java 是按值传递,而不是按引用传递。 </Emphasis>

 //I tried with studentMap.putAll(getStudentWithIdMap());
 // doing this triggers an exception like "UnsupportedOperationException"

这很可能是因为 Collections.emptyMap() return 是一个 不可变的 空映射。您正在尝试向其中添加元素。那不行。

创建空可变映射的方法是使用 new HashMap<>() 或类似方法。

 // I also tried studentMap = new HashMap<>(getStudentWithIdMap());

由于您当前的尝试失败,所以失败了。您正在创建一个新地图,并将其分配给一个参数变量......当您从 LoadData.

return 时,该变量将被丢弃

解决方法是什么?

可能会改变

  Map<String, Student> studentMap = Collections.emptyMap();

  Map<String, Student> studentMap = new HashMap<>();

将解决此问题...但您的问题中没有足够的上下文来判断这是否是 正确的 解决方案。 (你到底想在这里做什么?由 getStudentWithIdMap() 等 return 编辑的地图是否已经填充?)


I get to know Java treats method as value type always, so if passing a class object and modify its value, it would be modified after method finishes execution, why a Map behaves differently?

实际上,你需要回到教科书/教程/任何你学到的地方。重新阅读它。你在原来的阅读/理解中遗漏了一些非常重要的东西。

当您将一个对象(例如 Map)作为参数传递时,您会将对该对象的引用传递给被调用的方法。该引用被分配给局部变量。

  • 当您为该局部变量分配一个新引用时,它不会影响原始对象的状态或您从中获取引用的调用者中的变量。

  • 要更改您传递的对象的状态,您可以使用您传递的引用调用该对象的方法。


顺便说一句 LoadData 是一种风格违规。它应该被命名为 loadData.