kivok94
kivok94

Reputation: 303

HashMap to store data from other tables

i have those paths like this in array 'pc_list'

body/div[3]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div[1]/div[9]/div[2]
body/div[3]/div[2]/div/div[2]/div[3]/div[1]/div[2]
body/div[3]/div[2]/div/div[2]/div[4]/div[1]/div[1]

and in other table 'retrieved_elements' i have

body/div[3]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div[1]/div[9]/div[2]/div[2]/a = First 100 Words
body/div[3]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div[1]/div[9]/div[2]/div[3] = by Roger Priddy
body/div[3]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div[1]/div[9]/div[2]/div[6]/div[1]/strong = $3.98
body/div[3]/div[2]/div/div[2]/div[3]/div[1]/div[2]/div[2]/strong = $3.98
body/div[3]/div[2]/div/div[2]/div[3]/div[1]/div[2]/a/div[2] = First 100 Words
body/div[3]/div[2]/div/div[2]/div[4]/div[1]/div[1]/div[2]/strong = $3.98
body/div[3]/div[2]/div/div[2]/div[4]/div[1]/div[1]/a/div[2] = First 100 Words

in my code , i check if table retrieved_elements contains a path from table pc_liste , and then if it exist i save the value after "=" for exemple the result that get is like this :

body/div[3]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div[1]/div[9]/div[2]
 First 100 Words
 by Roger Priddy
 $3.98
body/div[3]/div[2]/div/div[2]/div[3]/div[1]/div[2]
 $3.98
 First 100 Words
body/div[3]/div[2]/div/div[2]/div[4]/div[1]/div[1]
 $3.98
 First 100 Words

but i want to save it in a map , in this step i found a problem , first this is my code :

HashMap<String, ArrayList<String>> map_instances = new HashMap<String, ArrayList<String>>();

pc_list = cp.checkSimilarity(retrieved_elements);
        for (int a = 0; a < pc_list.size(); a++) {
            String chemin_commun = pc_list.get(a);

           // System.out.println(chemin_commun);
            for (int b = 0; b < retrieved_elements.size(); b++) {

                String chemin_complet = retrieved_elements.get(b);

                if (chemin_complet.contains(chemin_commun)) {

                    chemin_complet = chemin_complet.split("=")[1];
                    inst_value.add(chemin_complet);
                    //System.out.println(chemin_complet);
                      map_instances.put(chemin_commun, inst_value);

                }
            }
            }
for (Map.Entry<String, ArrayList<String>> item : map_instances.entrySet()) {
            String key = item.getKey();
          System.out.println(item);
        }

but result of looping the map is like this :

body/div[3]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div[1]/div[9]/div[2]=[ First 100 Words,  by Roger Priddy,  $3.98,  $3.98,  First 100 Words,  $3.98,  First 100 Words]
body/div[3]/div[2]/div/div[2]/div[4]/div[1]/div[1]=[ First 100 Words,  by Roger Priddy,  $3.98,  $3.98,  First 100 Words,  $3.98,  First 100 Words]
body/div[3]/div[2]/div/div[2]/div[3]/div[1]/div[2]=[ First 100 Words,  by Roger Priddy,  $3.98,  $3.98,  First 100 Words,  $3.98,  First 100 Words]

instead of being like :

body/div[3]/div[2]/div/div[1]/div/div[2]/div/div[1]/div/div[1]/div[9]/div[2]=[ First 100 Words,  by Roger Priddy,  $3.98]
body/div[3]/div[2]/div/div[2]/div[4]/div[1]/div[1]=[ $3.98,  First 100 Words]
body/div[3]/div[2]/div/div[2]/div[3]/div[1]/div[2]=[$3.98,  First 100 Words]

Upvotes: 0

Views: 76

Answers (1)

RealSkeptic
RealSkeptic

Reputation: 34638

The trick is to have a different list object in each map entry.

The way you are doing this, you have a single list object, and you add all the values to that single object, and then put that single object as the value of all the mappings.

So forget about inst_value. Instead, when you find the first value for a certain chemin_commun, you create a new list and put it in the map. And the next time you find a value, you simply add to that new list you created. This makes sure that each chemin_commun has its own list, not a list shared between all.

So let's look at this piece of code:

if (chemin_complet.contains(chemin_commun)) {

    chemin_complet = chemin_complet.split("=")[1];
    inst_value.add(chemin_complet);
    //System.out.println(chemin_complet);
    map_instances.put(chemin_commun, inst_value);

}

Change it to:

if (chemin_complet.contains(chemin_commun)) {

    ArrayList<String> currentList = map_instances.get(chemin_commun);

    if ( currentList == null ) {
         // This is the first time we see this chemin_commun, so
         // Create a new list for it and put it in the map.
         currentList = new ArrayList<>();
         map_instances.put(chemin_commun, currentList );
    }

    // At this point currentList is never null. It is the specific list
    // that is mapped by the current chemin_commun. So add the value
    // to this list
    chemin_complet = chemin_complet.split("=")[1];
    currentList.add(chemin_complet);

}

A few general Java notes:

  • Variable and method names should not contain underscores. Java has code conventions. In short:
    • Type names (names of classes, interfaces, enums) should start with an uppercase letter and have a new uppercase letter at the beginning of every word, for example MyParser or VeryLongClassName.
    • Method and variable names should start with a lowercase letter and have an uppercase letter at the beginning of every new word. For example cheminCommun, cheminComplet etc.
    • Constants (final static fields or enum constants) are all in uppercase and they are the only ones where underscores separate words: BASE_SIZE, PROPERTY_NAME etc.)
  • Program to the interface, not to the class. That is, don't declare your variables as ArrayList but as List, not as HashMap but as Map. And then only assign a specific class to them. So your map should actually be declared:

    Map<String,List<String>> mapInstances = new HashMap<>();
    

    The declaration is with the interface Map (and List), the actual object is a HashMap. And then you'll declare currentList as List<String> instead of ArrayList<String>. If in the future you want to use a LinkedList or a TreeMap, it will be easier to change the code.

Upvotes: 1

Related Questions