简体   繁体   中英

Display HashMap of String and ArrayList

I got a hashmap of String and arraylist as value; When the values are:

<StringA: {element1,element2}, StrinbB: {null}>

The displaying of values (ie the ArrayList) always start with empty element. So it looks like:

{ , 1.element1 2.element2 }

Problems:

  1. Why first element is empty?
  2. Why there is no coma between two elements?

The function:

public String printTableNames(HashMap<String, ArrayList<String>> Map) {

        HashMap<String, ArrayList<String>> map = Map;  
        String s="\n\t\t Tables: ";
        Iterator<Entry<String, ArrayList<String>>> iter = map.entrySet().iterator();

        s= s + " { ";
        while (iter.hasNext()) {
            Entry<String, ArrayList<String>> entry = iter.next();

            List<String> l = new ArrayList<String>();

            l = entry.getValue();
            String temp="";
            for (int i=1; i<=l.size(); i++){

                temp= temp +" "+ Integer.toString(i)+"."+l.get(i-1);
            }               
            s = s + temp;

            if (iter.hasNext()) {
                s=s+",";
            }
            else s=s+" }";
        }
        return s;

    }

From HashMap apidoc:

This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.

That's why the values are not printed in the order of insertion. Some remarks on your code example, consider the following code:

 Map<String, List<String>> map = new HashMap<String, List<String>>() {{
        put("a", Arrays.asList(new String[]{"1","2"}));
        put("b", Arrays.asList(new String[]{"4","3"}));
 }};

 System.out.println(Arrays.deepToString(map.entrySet().toArray()));

it outputs:

[b=[4, 3], a=[1, 2]]

No need to write that many loops :) (unless you insist on printing the ordinals of each element, but in that case also there are other solutions)

Notice that I used the List interface in the HashMap declaration which allows me to use the Arrays.asList method in the initialization.

It is good practice to use interfaces instead of classes that implement the interface where applicable. It makes your code more flexible - eg if you want to replace your ArrayList with LinkedList for some reason, you just need to replace in the initialization statement and not all over your code.

relevant methods apidoc links:

It's printing out exactly what you're asking it to do.

A key point - a HashMap is theoretically defined as having no set order - you're expecting your results to be printed out in the order you inserted, Java is actually iterating through them in the opposite order. As such your print out shows the 'null' (not printed, given as an empty string), then a comma, then the next element.

There is no comma between your array elements because you haven't put one in your code, you've coded for commas between HashMap entries instead. Change this line for that:

temp= temp +" "+ Integer.toString(i)+"."+l.get(i-1);
if (i !=l.size()) temp += ',';

Output = { , 1.element1 2.element2 } tells that you have:

  • One List = Empty (It must be empty and not null, because otherwise you would be getting an NPE)
  • Other List = 1.element1, 2.element2

For a HashMap the order of keys' iteration is not same as the order in which they were inserted.

In your case empty list is iterated first followed by second list.

If you want to iterate in order of insertion order look at LinkedHashMap

As for the comma between your elements:

   temp= temp +" "+ Integer.toString(i)+"."+l.get(i-1) + ",";

should do. Though you might want to put a sepcial first element check if you don't want yur list to print as ele1,ele2,

The empty space is cause because of wrongly constructed pattern that you are using. You start with additional space " { " , in first run you skip the for, then you versifier that has next item and append "," . So you have " { ,". In next run you enter to loop and add space index and value.

Note the String type was used to store literals not modify. Use StringBuilder instead. I allow myself to fast rewrite your code and added a fix against NullPointer and the logic to avoid empty.

public String printTableNames(Map<String, List<String>> map) {

    StringBuilder builder = new StringBuilder("\n\t\t Tables:");

    builder.append(" { "); 

    for(Iterator<Entry<String, List<String>>> mapIterator = map.entrySet().iterator(); mapIterator.hasNext();) {

        List<String> values = mapIterator.next().getValue();

        if(values != null && !values.isEmpty()) { //We do not operate on null and empty list 
            int i=0; //As we have if block we enclose this so we do not need expensive values.get(i-1) to fetch value. 
            for(String value : values) {
                builder.append(' ');
                builder.append(i++);
                builder.append(value);
            }

        } else { 
            continue; //We skip the empty comma 
        }

        if(mapIterator.hasNext()) {
            builder.append(',');
        } 

    }

    builder.append(" }");

    return builder.toString();
}

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