0

Trying to use POJO in Key but unable to find match Any issue with current methodolgy How can I solve this?

public class test {
  public static void main(String a[]){`enter code here`
    HashMap<model, String> hm = new HashMap<model, String>();
    //add key-value pair to hashmap
    List<model> lm=new ArrayList<>();
   lm.add(new model(1,"1"));
   lm.add(new model(2,"2"));
   hm.put(lm.get(0), "1");
    System.out.println("Start");

    if (hm.containsKey(lm.stream().filter(person->person.name.equals("1")
            &&
            person.rollNo.equals(1)).findFirst())) {
        System.out.println("hit");
    }

}
static class  model{
    private Integer rollNo;
    private String name;

    @Override
    public boolean equals(Object obj) {
    model   modeltemp= (model)obj;
    if (modeltemp.name.equals(name)&& modeltemp.rollNo.equals(rollNo)) {
        return true;
    }
        return super.equals(obj);
    }
    public Integer getRollNo() {
        return rollNo;
    }
    public void setRollNo(Integer rollNo) {
        this.rollNo = rollNo;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public model(Integer rollNo, String name) {
        super();
        this.rollNo = rollNo;
        this.name = name;
    }

}
}
hellzone
  • 5,393
  • 25
  • 82
  • 148
fawad
  • 141
  • 2
  • 19
  • 1
    besides being super unclear, what is your actual question? – Eugene Apr 25 '18 at 11:30
  • See: https://stackoverflow.com/questions/18606447 – Jorn Vernee Apr 25 '18 at 11:30
  • do you understand how a HashMap key is being searched? equals AND hashcode... – Eugene Apr 25 '18 at 11:32
  • By using a key that is mutable, you expose yourself to nasty bugs. Do yourself a favour and use immutable keys. For guidance, see item 17: _Minimize mutability_ in Josh Bloch's _Effective Java_, 3rd ed. – jub0bs Apr 25 '18 at 21:15

1 Answers1

3

The very first problem is that you need to implement hashCode and equals, thus add a method to your Model (classes are uppercase):

@Override
public int hashCode() {
    return Objects.hash(getRollNo(), getName());
}

Then findFirst returns an Optional<Model>, not a Model. Since containsKey from HashMap accepts an Object as a parameter, this will work as a method call, but obviously nothing will be found.

You could simplify this (and make it more readable) via:

  Model m = list.stream()
            .filter(p -> p.name.equals("1"))
            .filter(p -> p.rollNo.equals(1))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("Key not found"));

  if (hm.containsKey(m)) {
        System.out.println("hit");
  }

Just notice that this throws an Exception if your list does not contain this person (you could do other things as well here - up to you)

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • Optional equals and hashcode delegate to the non null value, so if the model class was willing to test Optional, that could still work. Of course, the whole stream.filter... findfirst is just completely odd and makes it fail on top of the missing hashCode(). – user2023577 Apr 25 '18 at 11:52
  • @user2023577 right, assuming something like this would be in place `Model modeltemp; if (obj instanceof Optional) { modeltemp = ((Optional) obj).get(); } else { modeltemp = (Model) obj; }...` but I don't know if that would fit into the OP's model – Eugene Apr 25 '18 at 11:56
  • Optional should always be a return value, never an input argument anyway. – user2023577 Apr 25 '18 at 12:01
  • @user2023577 well... it is used as input in our project, so "sometimes" != "never"; though a null would be preferable in internal calls to denote a missing values I guess – Eugene Apr 25 '18 at 12:02
  • Well, so who's checking the optional is not null? See, it's not helping on input. Optional is a declaration from the method returning and should never extend beyond that. Notice that Optional is not serializable also to enforce that concept. – user2023577 Apr 25 '18 at 12:07
  • @user2023577 agreed again, I never understood why this was prohibited, but at the same time hashCode and equals was added, basically giving me the option to add those to a Set for example. If they really wanted to do it for return types only - this should have been prohibited also – Eugene Apr 25 '18 at 12:17
  • @fawad you probably just got lucky - without it there are no guarantees of what will happen – Eugene Apr 25 '18 at 14:20
  • @Eugene i added just 'Model m = list.stream() .filter(p -> p.name.equals("1")) .filter(p -> p.rollNo.equals(1)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("Key not found"));' as per your advice but didn't overide hascode just overidden the equals – fawad Apr 25 '18 at 14:25
  • @fawad your choice, just know that if this breaks in mysterious ways... – Eugene Apr 25 '18 at 14:26
  • @Eugene thanks for sharing the answer if you could share any scenario in the current example that can break it ,that would be really helpful – fawad Apr 25 '18 at 14:34
  • @fawad are you like asking for trouble not implementing hashCode here? It's like 3 to 5 lines of code. I don't understand you – Eugene Apr 25 '18 at 14:35
  • No admonition for using a mutable key? Using mutable keys for a hash map is a recipe for disaster. – jub0bs Apr 25 '18 at 21:12