简体   繁体   中英

Clear a HashMap after adding to a List, in Java

I would be very grateful if you could help me with the following Java code:

import java.util.ArrayList;
import java.util.HashMap;


public class JavaApplication2 {
    static ArrayList<HashMap> list_test = new ArrayList<HashMap>();
    static HashMap<String,String> test =new HashMap<>();
   
    public static void main(String[] args) {
        test.put("name", "jhon");
        test.put("lastname", "mckoy");
        list_test.add(test);
        test.clear();
        System.out.println(list_test);
        test.put("name", "Tom");
        test.put("lastname", "Red");
        list_test.add(test);
        
    }
    
}

I have two variables one called list_test (ArrayList ) and another called test (HashMap <String, String>). My goal is to make a ArrayList of HashMap using the following code, but after executing: test.clear (); then the content of list_test is deleted. Why? Is there another way to make a HashMap list? Which?

Thanks in advance

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

Solution:

  1. clone of 'test' (HashMap<String,String>)
  2. create new Map from 'test' (HashMap<String,String>)

Here is the code:

public class ListOfMapJavaApplication2 {
    static ArrayList<HashMap> list_test = new ArrayList<HashMap>();
    static HashMap<String,String> test =new HashMap<>();

    public static void main(String[] args) {
    test.put("name", "jhon");
    test.put("lastname", "mckoy");
    //list_test.add(new HashMap<String,String>(test));
    list_test.add((HashMap<String,String>)test.clone());
    test.clear();
    System.out.println(list_test);
    test.put("name", "Tom");
    test.put("lastname", "Red");
    //list_test.add(new HashMap<String,String>(test));
    list_test.add((HashMap<String,String>)test.clone());

    }
}

this is happing because of call by reference you can take new reference using the new keyword.

import java.util.ArrayList;
import java.util.HashMap;

public class Main
{
static ArrayList<HashMap> list_test = new ArrayList<HashMap>();
    static HashMap<String,String> test =new HashMap<>();
   
    public static void main(String[] args) {
        test.put("name", "jhon");
        test.put("lastname", "mckoy");
        list_test.add(test);
        test = new HashMap<>();
        System.out.println(list_test);
        test.put("name", "Tom");
        test.put("lastname", "Red");
        list_test.add(test);
        System.out.println(list_test);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM