1

I am doing dynamic programming in java and I came across this problem where the function takes three parameters, two of those are integers, and the third is an array of integers. I know that caching the value of a 1- or 2-parameter function can be implemented using a 1d/2d array. I am thinking of may be using a HashMap but I am trying to look for a nicer way to have those three indices bundled together as a key to the hashmap

1
  • Create a Key class that can contains those 3 values? Commented Jan 10, 2016 at 8:06

3 Answers 3

1

Create a new class which holds all parameters and add it to the map.
Make sure to also implement hashCode() & equals()

class MemoKey {
    Integer a;
    Integer b;
    Integer[] array;

    public MemoKey(Integer a,Integer b, Integer[] array) {
        this.a = a;
        this.b = b;
        this.array = array;
    }

    @Override
    public int hashCode() { 
        // implement 
    }

    @Override
    public boolean equals(Object obj) {
        // implement
    }
}

Then put this class in the map with your result Object.

HashMap map = new HashMap<MemoKey, Object>();

Object result = map.get(memoKey);
if (result == null)
    map.put(memoKey, calcResult());
Sign up to request clarification or add additional context in comments.

Comments

1

Here's an example, using Apache Commons Collections:

public static void main(String[] args) {

    MultiKeyMap multiKeyMap = new MultiKeyMap();

    int[] array1 = new int[10];
    int[] array2 = new int[10];

    multiKeyMap.put(13,52,array1, "First");
    multiKeyMap.put(81,22,array2, "Second");

    System.out.println(multiKeyMap.get(81,22,array2));  
}

3 Comments

Yes, that's the beauty of it. You can whatever you want as a key
In your code, multiKeyMap.get(81,22,array1) returns null. array1 and array2 have same value but different hash code value.
Of course it returns null; the two arrays are two different objects.
0

Create immutable class accepting two generics and an integer array as a constant type (you can change it to if you know that other numeric types will be used):

public final class CustomKey<F,S> {
private final F firstValue;
private final S secondValue;
private final int[] thirdValue;

public CustomKey(final F firstValue,
                 final S secondValue,
                 final Integer[] thirdValue){
    this.firstValue = firstValue;
    this.secondValue = secondValue;
    this.thirdValue = unboxingArray(thirdValue);
}

public S getSecondValue() {
    return secondValue;
}


public F getFirstValue() {
    return firstValue;
}

public int[] getThirdValue() {
    return thirdValue;
}

private static int[] unboxingArray(final Integer[] array){
    final int[] result = new int[array.length];
    IntStream.range(0,array.length)
            .forEach(index -> result[index] =  array[index]);
    return result;
}

@Override
public boolean equals(final Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    final CustomKey<?, ?> customKey = (CustomKey<?, ?>) o;
    return getFirstValue().equals(customKey.getFirstValue()) 
            && getSecondValue().equals(customKey.getSecondValue()) 
            && Arrays.equals(getThirdValue(), customKey.getThirdValue());

}

@Override
public int hashCode() {
    int result = getFirstValue().hashCode();
    result = 31 * result + getSecondValue().hashCode();
    result = 31 * result + Arrays.hashCode(getThirdValue());
    return result;
}

}

Unboxing of Integer array is necessary if you want to be able to compare integers in the array. If you will implement other type, do instanceOf check before unboxing.

Then, load your map as you would with any other key:

public static void main(String[]args){
    //Assume your Value is a String which does not really matter
    Map<CustomKey<Integer,Integer>,String> customKeyMap =
            new HashMap<>();
    customKeyMap.put(new CustomKey<>(1,2,new Integer[]{1,2,3}),"First Value");
    customKeyMap.put(new CustomKey<>(1,3,new Integer[]{1,2,3}),"Second Value");

    //Can use anonymous instance since equals is implemented
    //Expect Second Value
    System.out.println(customKeyMap.get(new CustomKey<>(1,3,new Integer[]{1,2,3})));
}

Comments

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.