4

What is the easiest way to create a HashMap like this :

( student1 => Map( name => Tim,         
                   Scores => Map( math => 10,
                                  physics => 20,
                                  Computers => 30),
                   place => Miami,
                   ranking => Array(2,8,1,13),
                ), 
student2 => Map ( 
                  ...............
                  ...............
                ),
............................
............................
);

I tried this :

HashMap record = new HashMap();
record.put("student1", new HashMap());
record.get("student1").put("name","Tim");
record.get("student1").put("Scores", new HashMap());

But I get error. I do it that way because, record.get("student1") is a HashMap object, so I assume a put on that should work, and so on.

If it doesnt work, what is the best way to do it ?

6
  • 3
    are you really sure you want map of maps instead of defining a class with attributes and maybe a map inside? Commented Jun 13, 2012 at 4:10
  • Yes, this is going to be a base data structure for one of my apps. I think you suggest a class because you see "Student" etc in the map. Actually that is just an example similar to the real requirement. Commented Jun 13, 2012 at 4:13
  • Maybe if you explain your functional requirement you could get better help from the community :) Commented Jun 13, 2012 at 4:15
  • You did not mention what your error was. Commented Jun 13, 2012 at 4:39
  • @george_h have you at least tried to copy/paste the code and compiled to check the "Object doesn't have the method" compile error? Commented Jun 13, 2012 at 4:56

7 Answers 7

4

You get that exception because get() returns a type Object. you need to cast that to a Map.

((Map)record.get("student1")).put("name","Tim");
Sign up to request clarification or add additional context in comments.

2 Comments

Thats right, its working now. See the 'Scores' in the example and if I can do it like this : ((HashMap)((HashMap)pages.get(student1)).get("Scores")).put("Math", 10);. But will there be an easier way to the casting ?
Yes, the easier way would be to create a class to hold the data, but you've already dismissed that idea in a previous comment. ;)
1

You can do it by type casting the Object to Map or HashMap.

HashMap record = new HashMap();
record.put("student1", new HashMap());
((HashMap)record.get("student1")).put("name","Tim");
((HashMap)record.get("student1")).put("Scores", new HashMap());

Still, as I've commented, are you sure you want this design?

Comments

1

Java is a statically and nominally typed language. As such the style of coding you are following is not preferable. You should be creating classes and objects instead.

That said, Guava provides several utility classes such as Lists, Iterables, Maps etc that let you construct the relevant collection objects from varargs.

Comments

1

While I agree with the other commenters about preferring to create proper classes for your domain objects, we can simplify the map construction syntax with some helper methods:

Map<String, Object> map = map(
    entry("student1", map(
        entry("name", "Tim"),
        entry("scores", map(
            entry("math", 10),
            entry("physics", 20),
            entry("Computers", 30)
        )),
        entry("place", "Miami"),
        entry("ranking", array(2, 8, 1, 13))
    )),
    entry("student2", map(
        // ...
    ))
);

// map.toString():
// {student2={}, student1={scores={math=10, physics=20, Computers=30}, name=Tim, place=Miami, ranking=[2, 8, 1, 13]}}

You just need to define a helper class like the one below and use a static import:

import static com.example.MapHelper.*;

The helper class:

package com.example;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MapHelper {

    public static class Entry {
        private String key;
        private Object value;

        public Entry(String key, Object value) {
            this.key = key;
            this.value = value;
        }

        public String getKey() {
            return key;
        }

        public Object getValue() {
            return value;
        }
    }

    public static Map<String, Object> map(Entry... entries) {
        Map<String, Object> map = new HashMap<String, Object>();
        for (Entry e : entries) {
            map.put(e.getKey(), e.getValue());
        }
        return map;
    }

    public static Entry entry(String k, Object v) {
        return new Entry(k, v);
    }

    public static List<Object> array(Object... items) {
        List<Object> list = new ArrayList<Object>(items.length);
        for (int i = 0; i < items.length; i++) {
            list.add(i, items[i]);
        }
        return list;
    }
}

Comments

0

Well the "Java" way to do this is to break up those entities into classes. From the example you gave, it looks like you can make a Student class that contains attributes like name, place, location, etc.

This is much cleaner than forcing everything into a map like this.

Comments

0

Why are you creating a complex set of HashMaps, you can create a Java Object instead, and then use it in for a HashMap.

So in your case, you can create a class called ScoreInfo which will have HashMap score, place and rank and then use that as a value of HashMap.

Comments

-1

Replace

HashMap record = new HashMap(); 

with

Map<String,Map<String, Object>> record = new HashMap<String,Map<String, Object>>();

But, this doesn't make much sense to put different object types as values. If the following line is by mistake,

record.get("student1").put("Scores", new HashMap());

then you can simplify the definition also.

Map<String,Map> record = new HashMap<String,Map>();

Assumption: You are using JDK 1.5+

3 Comments

That's not going to work, because the map has to contain things that are NOT maps.
Map can contain another Map and thats OPs requirement also. Didn't get when you said, this does not work. Can you clarify.
aa.. I now see his second put statement has new HashMap(). If thats the requirement (unless mityped), this doesn't work.

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.