seesee
seesee

Reputation: 1155

Optimization by avoiding object creation

Hello I am trying to avoid creating object by using normal array to store 2 key value, but it does not seems to work.

May I know is there any solution to avoid that one object creation or am I just trying too hard?

Forgotten to ADD:

1) I know why it does not work... I won't be implementing the equals() and hashcode() for key if I don't.

2) Basically I am trying to avoid 1 object creation when retrieving the key. Usually in the service class there will be a method

public void get(String key1, String key2){
       return keyMap.get(new Key(key1,key2)); <>>avoiding the new Key()
}

BREAK LINE

import java.util.HashMap;
import java.util.Map;


public class ArrayMap {

    /**
     * @param args
     */
    public static void main(String[] args) {

        /*start A  Possible to get this to work? */
        Map<String[], String> arrMap = new HashMap<>();
        arrMap.put(new String[] { "hello", "hi" }, "hello motto");
        System.out.println(arrMap);
        System.out.println(arrMap.get(new String[] { "hello", "hi" })); // print
                                                                        // null
         /* end of A */

        /*Start of B: Reason: to avoid this */
        Map<Key, String> keyMap = new HashMap<Key, String>();
        keyMap.put(new Key("hello", "hi"), "hello motto"); // I wish to avoid one object creation 

        System.out.println(keyMap.get(new Key("hello", "hi"))); // print
                                                                // "hello motto"
        /*End of B: Reason: to avoid this */
    }
}

class Key {
    private final String key1;
    private final String key2;

    public Key(String key1, String key2) {
        this.key1 = key1;
        this.key2 = key2;
    }

    public String getKey1() {
        return key1;
    }

    public String getKey2() {
        return key2;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((key1 == null) ? 0 : key1.hashCode());
        result = prime * result + ((key2 == null) ? 0 : key2.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Key other = (Key) obj;
        if (key1 == null) {
            if (other.key1 != null)
                return false;
        } else if (!key1.equals(other.key1))
            return false;
        if (key2 == null) {
            if (other.key2 != null)
                return false;
        } else if (!key2.equals(other.key2))
            return false;
        return true;
    }
}

Upvotes: 1

Views: 351

Answers (4)

CodeBlind
CodeBlind

Reputation: 4569

There are a couple of problems with this approach.

1. You can't override the equals()/hashcode() methods for arrays - This is an issue because the HashMap won't be able to correctly determine whether it has looked up the right key or not.

2. You're still creating new objects every time you want to create a key. Arrays are objects - you save nothing by creating a new one every time. Might as well use your original Key object.

Possible Solution

So I'm going to assume the reason why you want to avoid creating a new object every time is because you're going to be calling get(key) on that HashMap a LOT. If that's the case, why not create a mutable Key instance that remains internal to your ArrayMap object. Every time you want to key on two Strings, simply set them in your mutable Key instance and use that mutable instance for the lookup. Then you don't create a new Key every time you want to look up a value for a pair of Strings.

Upvotes: 4

NPE
NPE

Reputation: 500357

May I know is there any solution to avoid that one object creation or am I just trying too hard?

If you are unsure whether you're trying too hard, then you probably are. Based on the information you've given us, this looks like premature optimization.

A couple of pertinent points:

  1. Object creation is not expensive, especially if the object is short-lived.
  2. The only way to be sure of the performance characteristics of a piece of software is through profiling.

Upvotes: 2

Blake
Blake

Reputation: 591

In java, array1.equals(array2) only if array1 == array2, i.e. they are the same exact instance in memory. So that causes the Map to view them as separate keys. You're better off going with your Key class for the map's key

Upvotes: 1

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279970

In these lines

arrMap.put(new String[] { "hello", "hi" }, "hello motto");
System.out.println(arrMap);
System.out.println(arrMap.get(new String[] { "hello", "hi" })); // print
                                                                    // null

you use a String[] as a key. That object doesn't have a custom equals() method like the one you have in your Key class where you can compare the contents. So when you try to do map.get() passing in a new String[] (but with the same content), it won't find anything because it's not the same object.

What you might want to do is this

String[] array = new String[] { "hello", "hi" };
arrMap.put(array , "hello motto");
System.out.println(arrMap);
System.out.println(arrMap.get(array)); // print hello motto

You really shouldn't use array types as keys to Maps.

Upvotes: 2

Related Questions