1

I have a class: Question

It has id and content.

I have a HashMap with Questions as keys and asnwers(Strings) as values.

I try to lookup an answer from my map, using a Question for key.

However it always gives null value and I don't know why because the map does contains my Question.

Code:

            Log.i("info", "map:");
            Log.i("info", questionAnswers.toString());
            Log.i("info", "================================");

            Log.i("info", "question we are looking for:");
            Log.i("info", question.toString());
            Log.i("info", "================================");

            Log.i("info", "anwer is null: " + questionAnswers.get(question));
            Log.i("info", "================================");

            Iterator it = questionAnswers.entrySet().iterator();

            //Iterating the map just to get information for test's sake
            while (it.hasNext()) {

                Map.Entry<Question, String> entry = (Map.Entry<Question, String>) it.next();

                //Question in the map
                Question questionInCont = entry.getKey();

                //Testing the equals method
                if (questionInCont.equals(question)) {


                    Log.i("info", "================================");
                    Log.i("info", "question we are looking for is equals to a question in the map");
                    Log.i("info", questionInCont.getQuestionId() + " == " + question.getQuestionId());

                    String answer = questionAnswers.get(question);

                    //Great, equals working but still no answer back, only null
                    Log.i("info", "anwer is still null: " + answer);
                    Log.i("info", "================================");
                }
            }

Log output:

11-21 13:22:13.083: I/info(18350): map:
11-21 13:22:13.083: I/info(18350): {Question{questionId='9', content='What is your name?'}=John, Question{questionId='8', content='How old are you?'}=33}
11-21 13:22:13.083: I/info(18350): ================================
11-21 13:22:13.083: I/info(18350): question we are looking for:
11-21 13:22:13.084: I/info(18350): Question{questionId='8', content='How old are you?'}
11-21 13:22:13.084: I/info(18350): ================================
11-21 13:22:13.084: I/info(18350): anwer is null: null
11-21 13:22:13.084: I/info(18350): ================================
11-21 13:22:13.084: I/info(18350): ================================
11-21 13:22:13.084: I/info(18350): question we are looking for is equals to a question in the map
11-21 13:22:13.084: I/info(18350): 8 == 8
11-21 13:22:13.084: I/info(18350): anwer is still null: null
11-21 13:22:13.084: I/info(18350): ================================

So as you can see:

  1. My HashMap does contain the question Im looking for.
  2. It does have an answer (value)
  3. The questions equals method does returns true when both questions have the same id.

E D I T :

Thanks for the comments, my question class does not have hashCode() function. Is it the problem?

Question class:


public class Question implements Serializable {

    String questionId;
    String content;


    public Question(String id, String content) {
        this.questionId = id;
        this.content = content;
    }


    @Override
    public boolean equals(Object obj) {

        if (obj instanceof Question) {
            Question question = (Question) obj;
            return questionId.equals(question.getQuestionId());
        }

        return false;
    }
 }

Sow why why I got null as the answer?

Adam Varhegyi
  • 11,307
  • 33
  • 124
  • 222
  • 3
    You probably didn´t override the `hashCode` properly as the `HashMap` works with this method. – SomeJavaGuy Nov 21 '16 at 12:35
  • 4
    Show the Question class, and show how you populate the map. You probably modify the question after it's stored in the map, thus changing its hashCode. Or you just didn't override equals() and hashCode(). – JB Nizet Nov 21 '16 at 12:35
  • Overwrite the .equals method and hashCode method. – k1133 Nov 21 '16 at 12:38

3 Answers3

5

Your main problem is that you only implement the equals() method. This is strictly forbidden for values of a HashMap because equals() always has to be implemented together with hashCode().

Every entry (m1) and a second entry (m2) in a HashMap the following must be true: m1.equals(m2) implies that m1.hashCode()==m2.hashCode()

Robert
  • 39,162
  • 17
  • 99
  • 152
1

You must overide the hashCode method for the class which is used as a key in HashMap.

It could be as simple as :

@Override
public int hashCode() {
    return questionId.hashCode();
}
Orabîg
  • 11,718
  • 6
  • 38
  • 58
0

As other have said, the HashMap may not be able to retrieve the entry associated with your key because your Question class is missing the override of the hashCode() function (see this for reference: https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()).

I would suggest to implement the function as follows:

@Override
public int hashCode() {
     return questionId.hashCode() + content.hashCode();
}

The general rule is that If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result. (from the link above).