Home > OS >  Java 8 - Stream API - groupingby not working
Java 8 - Stream API - groupingby not working

Time:08-30

I want to use the Stream API to group a list of persons by name and city. I have following code (in Java 8):

    class Person {
        private String name;
        private String gender;
        private String city;
        
        Person(String name, String gender, String city) {
            this.name   = name;
            this.gender = gender;
            this.city   = city;
        }
    }
    
    class PGroup {
        final String name;
        final String city;
        
        public PGroup(String name, String city) {
            this.name = name;
            this.city = city;
        }       
    }
    
    List<Person> people = new ArrayList<>();
    people.add(new Person("Thomas", "M", "Cologne"));
    people.add(new Person("Wilma",  "F", "Cologne"));
    people.add(new Person("Lydia",  "F", "Munich"));
    people.add(new Person("Thomas", "M", "Cologne"));
    
    Map<PGroup, List<Person>> map = people.stream()
            .collect(Collectors.groupingBy(t -> new PGroup(t.name, t.city)));
    
    for (PGroup p : map.keySet()) {
        System.out.println("name: "   p.name   ", city: "   p.city);
    }

If I run this code I get:

name: Wilma, city: Cologne
name: Thomas, city: Cologne
name: Lydia, city: Munich
name: Thomas, city: Cologne

As we can see the List was not grouped at all. I expect only 3 entries, since Thomas in Cologne exists twice and we want to group by name and city:

name: Wilma, city: Cologne
name: Thomas, city: Cologne
name: Lydia, city: Munich

Why it is not grouped? What I am missing please?

CodePudding user response:

Try to override the equals and hashcode functions of PGroup class. Try to replace the class code with below:

class PGroup {
    final String name;
    final String city;

    public PGroup(String name, String city) {
        this.name = name;
        this.city = city;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof PGroup)) return false;
        PGroup pGroup = (PGroup) o;
        return Objects.equals(name, pGroup.name) && Objects.equals(city, pGroup.city);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, city);
    }
}

Reason: The default implementation of the .equals() method compares the object references or the memory location where the objects are stored in the heap. Thus by default the .equals() method checks the object by using the “==” operator. Read more on equals and hashcode functions here

  • Related