0

I am new to Java and I tried a couple of ways to initialize my HashMap through a method, but every time after method executed, my Map is still empty, I can debug and see during my LoadData method execution, my maps are assigned with value from sub-method, however, when jumping out of the LoadData, my outer parameter becomes empty Map again

// 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, ...);
}

What would be the reason and the best way to deal with the above scenario?

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?

Drex
  • 3,346
  • 9
  • 33
  • 58

2 Answers2

1

If you do something like

 studentMap = getStudentWithIdMap();

The variable studentMap will point to the Map return by getStudentwithIdMap(); that doesn't affect the Map referenced in variable studentMap in the PrepareData method.

To actually change that Map you need to insert the values into it.

E.g with:

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

That will cause another Problem, because you initialized these variables with Collection.emptyMap(). You are not allowed to change that map, so writes will fail.

This can be fixed with:

public void PrepareData() {
   Map<String, Student> studentMap = new HashMap<>();
   Map<String, Teacher> teacherMap = new HashMap<>();
   file1.LoadData(studentMap, teacherMap, ...);
}
k5_
  • 5,450
  • 2
  • 19
  • 27
1

Your code doesn't make a lot of sense to me:

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

That assignment is assigning to a parameter. It is a reference assignment. It won't affect the map that was passed as a parameter.

<Emphasis> Java is pass-by-value, not pass-by-reference. </Emphasis>

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

That is most likely because Collections.emptyMap() returns an immutable empty map. You are trying to add elements to it. That won't work.

The way to create an empty mutable map is to use new HashMap<>() or similar.

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

That fails for the reason that your current attempt fails. You are creating a new map, and assigning it to a parameter variable ... which is discarded when you return from LoadData.


What is the solution?

Possibly changing

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

to

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

will solve this ... but there is insufficient context in your Question to know if this is the correct solution. (What are you really trying to do here? Are the maps returned by getStudentWithIdMap() etcetera already populated?)


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?

Actually, you need to go back to the textbook / tutorial / whatever where you learned that. Re-read it. You have missed something very important in your original reading / understanding.

When you pass an object (e.g. a Map) as a parameter, you are passing the reference to the object to the called method. That reference is assigned to a local variable.

  • When you assign a new reference to that local variable, it does not affect the state of the original object OR the variable in the caller where you got the reference from.

  • To change the state of the object that you passed, you call a method on the object using the reference that you passed.


By the way LoadData is a style violation. It should be named loadData.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216