Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant way to overcome Unlikely argument type for equals(): Stream<String> seems to be unrelated to String

I am looking for elegant way to overcome while comparing any Wrapper object to Stream.

Github working link: https://github.com/vishwaratna/Unlikely-argument-type-for-equals-Stream-String-/commit/d803f77c923e81fe7531ecb467561ac785d7aca5

Question in reference: Filtering keys from map to list attribute in java-8

Recently i faced it while comparing member of List to a key of a Map. I know there are other ways to compare without doing what i am doing but i am looking for in general casting, if it is available.

List<student> stulist = Arrays.asList(new student("1", "vishwa",null),
                                              new student("3", "Ravi",null),
                                              new student("2", "Ram",null));

        Map<String,String> map = new HashMap() {{
             put("1","20");
             put("2","30");
           }};

System.out.println( stulist.stream()
                    .filter(s->s.getId()
                    .equals(map.entrySet()
                    .stream() 
                    .map(Map.Entry::getKey)))
                    .count());

My code is compiling properly but the output is coming as "0", whereas i expect output as 2.

I am sure it is due to type mismatch, but why the compiler is not throwing an error??

Warning that i am getting: Unlikely argument type for equals(): Stream<String> seems to be unrelated to String

like image 560
Vishwa Ratna Avatar asked Feb 18 '19 11:02

Vishwa Ratna


2 Answers

Basically, to understand why compiler doesn't give an error, you should look into String.equals() method implementation

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

Now, let's go back to this line:

s.getId().equals(map.entrySet().stream().map(Map.Entry::getKey))

As we know s.getId() is of type String and map.entrySet().stream().map(Map.Entry::getKey) is of type Stream<String>.

Since Stream<String> is not instanceof String, it's clear that String.equals() method will return false each time s.getId() is compared with map.entrySet().stream().map(Map.Entry::getKey) (hence, 0 count at the end). And compiler doesn't issue error, because nothing illegal actually happened (taking into account implementation of String.equals()).

Also, probably, cleanest way to find count without warnings would be:

System.out.println(
  stulist.stream()
         .map(Student::getId)
         .filter(map::containsKey)
         .count());
like image 198
Oleksii Zghurskyi Avatar answered Sep 20 '22 07:09

Oleksii Zghurskyi


First, what you might be intending to there could be:

System.out.println(stulist.stream()
        .filter(s -> map.keySet().contains(s.getId()))
        .count());

Second, the comparison using equals in your code is incorrect since its between objects of two different types of String and Stream<String>.

// here the 's.getId' is a String while 'map.entrySet()...map()' provides 'Stream<String>'
.filter(s -> s.getId().equals(map.entrySet().stream().map(Map.Entry::getKey)))
like image 29
Naman Avatar answered Sep 21 '22 07:09

Naman