cryptonkid
cryptonkid

Reputation: 994

Storing a HashMap inside another HashMap and improving performance

I am supposed to created a HashMap inside another HashMap as shown below which can store the value inside the inner HashMap based on the key of the outer HashMap at the runtime

i.e. required output for program should be of the format

   { 1 = {11 = "aaa",15 = "bbb"}, 2 = {13 = "ccc", 14 = "ddd"} }

where 1,2 are Key values for Outer HashMap.

Below is the Code provided for it Is there any better approach to improve performance

HashMap<Integer, HashMap<Integer, String>>Outer 
                   = new HashMap<Integer, HashMap<Integer,String>>();

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    int count = Integer.parseInt(br.readLine());
    for(int i =0;i<count;i++)
    {
        String input[] = br.readLine().split("\\s");

        //HashMap<Integer,String>inner = new HashMap<Integer, String>();
        int key = Integer.parseInt(input[0]);
        if(Outer.isEmpty() || !Outer.containsKey(key))
        {
            HashMap<Integer, String> inner = new HashMap<Integer, String>();
            inner.put(Integer.parseInt(input[1]),input[2]);
            Outer.put(key, inner);
        }
        else if(Outer.containsKey(key))
            {
                HashMap<Integer, String> inner = (HashMap<Integer, String>) Outer.get(key).clone();
                inner.put(Integer.parseInt(input[1]), input[2]);
                Outer.put(key, inner);
            }
    }

Upvotes: 10

Views: 32144

Answers (3)

toto2
toto2

Reputation: 5326

Optimizing is nearly always a bad idea. Especially in Java where the JVM is quite good at doing that by itself.

Do you really need a Map<Integer, Map<Integer, String>>, it seems to me that you really just need a Map<Pair, String> where

public final class Pair {
  private final int x;
  private final int y;
  public Pair(int x, int y) { this.x = x; this.y = y;}
}

I am not claiming at all that this will improve performance, but it might be better design. I don't quite know what you are doing, so maybe it's not better design.

Upvotes: 3

ziesemer
ziesemer

Reputation: 28687

Similar to Vadim's answer, but further improved - as it doesn't require a call to both containsKey as well as get:

Map<Integer, Map<Integer, String>> outer = new HashMap<Integer, Map<Integer, String>>();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int count = Integer.parseInt(br.readLine());

Pattern splitter = Pattern.compile("\\s");

for(int i = 0; i < count; i++){
    String input[] = splitter.split(br.readLine());

    int key = Integer.parseInt(input[0]);

    Map<Integer, String> inner = outer.get(key);
    if(inner == null){
        inner = new HashMap<Integer, String>();
        outer.put(key, inner);
    }
    inner.put(Integer.parseInt(input[1]), input[2]);
}

It also has some minor improvements for naming conventions, and use of the Collections interfaces instead of concrete types.

I also removed the call to clone. This could be a slight savings - and I don't think it would have given you your expected results.

Finally - one other thing that I changed that could be a slight improvement is using a pre-compiled Pattern for the splitting of your String into fields.

Upvotes: 6

Vadim Gulyakin
Vadim Gulyakin

Reputation: 1431

Your code is good enough from performance point of view. Only few things came to my mind. If/else condition can be simplified and you don't need to clone map in else part (work with pointer)

HashMap<Integer, HashMap<Integer, String>>Outer = new HashMap<Integer,   HashMap<Integer,String>>();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int count = Integer.parseInt(br.readLine());
for(int i =0;i<count;i++)
{
    String input[] = br.readLine().split("\\s");

    //HashMap<Integer,String>inner = new HashMap<Integer, String>();
    int key = Integer.parseInt(input[0]);
    if(!Outer.containsKey(key))
    {
        HashMap<Integer, String> inner = new HashMap<Integer, String>();
        inner.put(Integer.parseInt(input[1]),input[2]);
        Outer.put(key, inner);
    }
    else
    {
        HashMap<Integer, String> inner = Outer.get(key);
        inner.put(Integer.parseInt(input[1]), input[2]);
    }
}

Upvotes: 2

Related Questions