1

I want to create a hashmap defined as HashMap<Character,ArrayList<String>>. What I am trying to do is to read a set of strings which I am reading into a list. From this list I want to generate this hashmap. So if strings are something like this

Andy,Aman,Rocky,Ravi,Nick etc. Map should be like

A->[Andy,Aman]
R->[Rocky,Ravi]
N->Nick

What I have tried is something like this

ArrayList<String> xlist= new ArrayList<String>();
    ArrayList<String> list = new ArrayList<String>();
    HashMap<Character,ArrayList<String>> h = new HashMap<Character,ArrayList<String>>();
    Scanner s = new Scanner(System.in);
    for(String sin : list){
        Character x =sin.charAt(0);
        //System.out.println(sin.charAt(0));
        if(h.containsKey(x)){
            h.get(x).add(sin);
            //xlist.clear();
            //xlist = h.get(x);
            //xlist.add(sin);
            //h.put(x,xlist.clone());

        }
        else{
            xlist.clear();
            xlist.add(sin);
            h.put(x,xlist);

        }
    }

When I print the hashmap, I get this

{A=[Ravi, Rocky], R=[Ravi, Rocky], N=[Ravi, Rocky]}

I understand , that all the lists in values are being reflected from same copy of list, but I don't know , how to resolve it.

2 Answers 2

3

If you don't want to rewrite the loop, you can just change your last line within the else block so you won't change content of map on every iteration:

h.put(x,new ArrayList<String>(Arrays.asList(sin)));

You can also do it using Java 8 Streams which makes it much shorter:

Map<Character, List<String>> map = list.stream().collect(Collectors.groupingBy(d -> d.charAt(0)));

If you want to preserve the order of keys you can use it with LinkedHashMap:

Map<Character, List<String>> map = list.stream().collect(Collectors.groupingBy(d->d.charAt(0), LinkedHashMap::new, Collectors.toList()));
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Kamil, that was so stupid of me, its looking so obvious now.
1

xlist is always the same list, even after you've put it in your hashmap. Whenever you hit a new letter, you clear every list in your hashmap, and add the current word to every list, because they're all the same list.

I'd rewrite your loop as:

for(String sin : list){
    Character x =sin.charAt(0);
    if(!h.containsKey(x)){
        h.put(x, new ArrayList<String>());
    }
    h.get(x).add(sin);
}

2 Comments

With Java 8, you can replace the whole loop body with h.computeIfAbsent(sin.charAt(0), c -> new ArrayList<>()).add(sin);
@Andrew Ruekert: Thanks Kamil, that was so stupid of me, its looking so obvious now.Much cleaner loop now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.