tl;dr
With your code, the same map object that you put in the list is the same map object that you clear. Instead, add a copy of your map into your list.
listOfMapsOfNames.add( Map.copyOf( mapOfNames ) ); // Make an unmodifiable copy of map to be added to list.
Make a copy of your map
Apparently you want a copy of your map added to the list.
Your code puts the original map into the list. So now you have two references to the same map: (a) the variable test
points to the map, and (b) the first element in the list named list_test
points to the very same map object. If you use either reference to change the map's contents, both references see that change, given that they both point to the same object.
Either:
- Call
Map.copyOf
to make an unmodifiable copy of the map. Ex: Map.copyOf( oldMap )
- Pass the map to the constructor of another
Map
implementation to copy the entries over to a new modifiable map. Ex: new HashMap<>( oldMap )
.
You should consider making a habit of using the more general superclass or interface rather than concrete class in your references, where practical. So List<Map> list_test
rather than ArrayList<HashMap> list_test
.
You should parameterize the parameterization of your List
. So List< Map< String, String > >
rather than List< Map >
.
Using more descriptive names on your Java identifiers will make your code easier to read and debug. So something like listOfMapsOfNames
rather than list_test
.
Example code
Here is some example code.
I dropped the static
on the map and list as that is irrelevant.
Notice the two calls Map.copyOf( mapOfNames )
.
List< Map< String, String > > listOfMapsOfNames = new ArrayList<>() ;
Map< String, String > mapOfNames = new HashMap<>() ;
mapOfNames.put( "name", "John" );
mapOfNames.put( "lastname", "McKoy" );
listOfMapsOfNames.add( Map.copyOf( mapOfNames ) ); // Make an unmodifiable copy of map to be added to list.
System.out.println( "map before clear: " + mapOfNames );
mapOfNames.clear();
System.out.println( "map after clear: " + mapOfNames );
mapOfNames.put( "name", "Tom" );
mapOfNames.put( "lastname" , "Red" );
listOfMapsOfNames.add( Map.copyOf( mapOfNames ) ); // Make an unmodifiable copy of map to be added to list.
System.out.println( "map after 2nd add: " + mapOfNames );
System.out.println( "list at the end: " + listOfMapsOfNames );
See this code run live at IdeOne.com.
map before clear: {name=John, lastname=McKoy}
map after clear: {}
map after 2nd add: {name=Tom, lastname=Red}
list at the end: [{lastname=McKoy, name=John}, {lastname=Red, name=Tom}]
record
Not relevant to your Question, but for your information, the use of a class might make more sense than using a Map
for tracking first name and last name. And now we have an easier way to write such a class: records.
The records feature is new in Java 16. A record is a brief way to write a class whose main purpose is to communicate data transparently and immutably. The compiler implicitly creates the constructor, getters, equals
& hashCode
, and toString
. Bonus: A record can be declared locally as well as being declared nested or separate.
Notice the following version of your code becomes more expressive (and shorter) with record
.
record Person(String firstName , String lastName) {}
List < Person > people = new ArrayList <>();
people.add( new Person( "John" , "McKoy" ) );
people.add( new Person( "Tom" , "Red" ) );
people.toString(): [Person[firstName=John, lastName=McKoy], Person[firstName=Tom, lastName=Red]]