Sophie Sperner
Sophie Sperner

Reputation: 4556

HashMap Object key

In Java, I have a class:

public static class Key {

    int[] vector = null;

    private int hashcode = 0;

    Key (int[] key) {
        vector = new int[key.length];
        // here is the problem
        System.arraycopy(key, 0, vector, 0, key.length);
    }

    public int hashCode() { ... }

    public boolean equals(Object o) { ... }

}

which acts as a key in the HashMap<Key, int[]> map. In code I do:

// value int[] array is filled before
map.put(new Key(new int[] {5, 7}), value);

But this creates an argument array {5, 7} twice - first time when Key constructor is called and then inside that constructor.

I can not use HashMap<int[], int[]> map because then it is not clear what hashCode will be used for int[]. So I wrap up the int[] key inside Key class.

How is it possible to create an argument array (which can be of different size) just once?

I do not like this solution:

map.put(new Key(5, 7), value);

// and rewrite the constructor
Key (int a1, int a2) {
    vector = new int[2];
    vector[0] = a1;
    vector[1] = a2;
}

because generally an argument array can be of various size.

Upvotes: 1

Views: 621

Answers (3)

Bizmarck
Bizmarck

Reputation: 2698

Since arraycopy is being used to do a deep copy from one object to another, at some point you need to create two objects where the second is the same size as the argument array. So vector = new int[key.length]; looks correct.

Btw, when I compile your code I get an error that static is not a valid modifier for class, only public, abstract, or final are.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726987

How is it possible to create an argument array (which can be of different size) just once?

Unfortunately, you cannot do that, because there is no way to make a built-in Java array immutable. If it were possible to make immutable arrays, the following would work:

Key (int[] key) {
    // Do not do this!!!
    vector = key;
}

Although the above would work in fully cooperative environments, hostile users could pass an array, and let the key calculate the hash, and then change array elements to introduce errors into your code. That's why you are absolutely right when you decided to copy the array passed in.

You can change the function to accept variable number of arguments, like this:

Key (int ... key) {
    vector = new int[key.length];
    System.arraycopy(key, 0, vector, 0, key.length);
}

This would let you create arrays implicitly rather than explicitly:

map.put(new Key(5, 7), value);

Upvotes: 3

Bohemian
Bohemian

Reputation: 425308

Use varargs for the parameter and use Arrays.copyOf():

Key (int... key) {
    vector = Arrays.copyOf(key, key.length);
}

Now you can call the constructor with any number if int parameters (including no parameters) and it won't cause an error.

Upvotes: 1

Related Questions