kaixas K kaixas K - 1 month ago 9
Java Question

HashMap repeating the last element

I am trying to create a

HashMap
in a
HashMap
so it will be easier for me to access elements of it in the future as shown below.

The problem is it only repeating the last elements of the
while
loop and not the rest of it.

HashMap<String,String> result = new HashMap<>();
HashMap<Integer, HashMap<String,String>> fr = new HashMap<>();

int i = 0;
try {
ResultSet rq = qexec.execSelect();
// ResultSetFormatter.out(System.out, rq, query);

// get result from SPARQL query
while (rq.hasNext()) {
QuerySolution soln = rq.next();
id = soln.getLiteral("?id").getLexicalForm();
//...
result.put("id",id);
//...
if (soln.getLiteral("?wateruse") != null) {
wateruse = soln.getLiteral("?wateruse").getLexicalForm();
//...
result.put("wateruse",wateruse);
} else {
System.out.println("NO");
}

fr.put(i, result);
i++;
}
} finally {
qexec.close();
}


This is how the result should be:

John001
High usage
John002
John003
Smith001
Moderate
Smith002
Smith003
...
Kevin001
Low usage


But
fr
only repeats
Kevin001
and
Low usage
without the rest.

I've tried to put
fr.put(i,result)
outside the loop but that still does not give the correct result.

EDIT

I tried to print all elements from
fr
that shows the repeating elements.


finally {

qexec.close();
}


for (int index : fr.keySet()) {
for(Map.Entry<String, String> entry :result.entrySet()) {
System.out.println(index + " = " + entry.getKey() + " : " + entry.getValue());
}
}




UPDATE - SOLUTION

Declare
HashMap
inside the loop as mentioned in comments below.

To print nested HashMap, no need to use
result
.
I did as shown below and it prints both
outermap
and
innermap
as well.

for (int k=0; k < fr.size(); k++) {
HashMap<String,String> innermap = fr.get(k);
for(Map.Entry<String, String> e : innermap.entrySet()) {
System.out.println(k + " = " + e.getKey() + " : " + e.getValue());
}
}



Answer Source

You're adding the same result map to your parent map each time through the loop. Create a new instance of result each time through the loop:

Map<String, String> result = new HashMap<>();
Map<Integer, Map<String, String>> fr = new HashMap<>();

int i = 0;
try {

    ResultSet rq = qexec.execSelect();

    while (rq.hasNext()) {

        // Create your new HashMap inside the loop:
        result = new HashMap<>();

        QuerySolution soln = rq.next();

        id = soln.getLiteral("?id").getLexicalForm();
        //...

        result.put("id",id);
        //...

        if (soln.getLiteral("?wateruse") != null) {

            wateruse = soln.getLiteral("?wateruse").getLexicalForm();
            //...
            result.put("wateruse",wateruse);
        }
        else {
            System.out.println("NO");
        }               

        fr.put(i,result);
        i++;
    }
}

To print the results from fr an its nested map, you can do something like this:

for (Map<String, String> map : fr.values()) {
    for(Map.Entry<String, String> e : map.entrySet()) {
        System.out.println(index + " = " + e.getKey() 
            + " : " + e.getValue());
    }
}