2

I am having trouble on how to retrieve the Value from a Map indexed with custom Objects. In my case I have a Map with a Model object as Key and a List of objects as Value. The Map seems to be well populated because I've iterated through each Key and printed all Model objects to console.

My question is how to get Value from a specific entry in the Map.

Map<Model, Parameter> mapSet = m.getMyMap()

for(Entry<Model, Parameter> entry : mapSet){
    println entry.key.getModel() //prints each Model
}

List<Parameter> testListBase = mapSet.get(new Model("BASE"))

List<Parameter> testListSearch = mapSet.get(new Model("SEARCH"))

Do I have to override hashCode() and equals() from Object to retrieve the list for that entry in the Map?

UPDATE

Here it is the simple Model object, but still cannot retrieve the key using

mapSet.get(new Model("BASE"))

public final class Model {

private final String model;
private final static int count = 0;
private int id;

private Model(String model){
    this.model = model;
    id = ++count;
}

private String getModel(){
    return model;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + id;
    result = prime * result + ((model == null) ? 0 : model.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;
    }
    Model other = (Model) obj;
    if (id != other.id) {
        return false;
    }
    if (model == null) {
        if (other.model != null) {
            return false;
        }
    } else if (!model.equals(other.model)) {
        return false;
    }
    return true;
}

}

6
  • 3
    Yes, of course. Otherwise, a Model object is only equal to itself. Commented Dec 19, 2015 at 18:05
  • Your hashCode and equals are not working because they take the Model id into account. For example the assertion assert new Model ("hello") == new Model ("hello") fails because both models have different id's. You can fix this by excluding the id from the hashCode and equals. Commented Dec 21, 2015 at 12:57
  • I changed both hashCode() and equals() and now I have a StackOverflowError Commented Dec 21, 2015 at 13:17
  • Since the model name (the field named model) is the only thing that establishes equality, then you can simply have hashCode() and equals() delegate to the String model. Ex: public int hashCode() { model.hashCode() }, public boolean equals(Object obj) { model.equals(obj) } . Commented Dec 21, 2015 at 14:39
  • It is not working even if I delegate... Commented Dec 22, 2015 at 12:15

1 Answer 1

4

Yes, Model must implement hashCode() and equals(Object).

...great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map. - http://docs.oracle.com/javase/7/docs/api/java/util/Map.html

You may be able to implement hashCode() and equals(Object) quite easily using Groovy's EqualsAndHashCode AST transformation. Here's a working example:

@groovy.transform.TupleConstructor
@groovy.transform.EqualsAndHashCode
class Model {
    String name
}

@groovy.transform.TupleConstructor
class Parameter {
    String name
}

Map<Model, List<Parameter>> mapSet = [
    (new Model('BASE')): [
        new Parameter('Some parameter'), 
        new Parameter('Another parameter')
    ],

    (new Model('SEARCH')): [
        new Parameter('Yet another parameter'), 
        new Parameter('And yet another parameter')
    ]
]

for(Map.Entry<Model, List<Parameter>> entry: mapSet) {
    println entry.key // Prints each Model
}

List<Parameter> testListBase = mapSet.get(new Model("BASE"))
List<Parameter> testListSearch = mapSet.get(new Model("SEARCH"))

assert testListBase*.name.containsAll(['Some parameter', 'Another parameter'])
assert testListSearch*.name.containsAll(['Yet another parameter', 'And yet another parameter'])

I used the TupleConstructor AST for convenience, but the work-horse here is EqualsAndHashCode. Note that I assumed your intention and therefore deviated from your example to code what you said:

...a Map with a Model object as Key and a List of objects as Value.

The EqualsAndHashCode documentation describes how to tweak the default behaviour, in case you need to.

Sign up to request clarification or add additional context in comments.

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.