3

lets us suppose I have a Employee list as :

private static List<Employee> list = new ArrayList<Employee>();
    static {
        list.add(new Employee("Joe", 100000, 1980));
        list.add(new Employee("Tim", 50000, 1982));
        list.add(new Employee("Mike", 90000, 1970));
        list.add(new Employee("Rick", 50000, 1955));
        list.add(new Employee("Andy", 60000, 1966));
        list.add(new Employee("Tim", 10000, 1995));
        list.add(new Employee("Tony", 130000, 1991));
        list.add(new Employee("Timmy", 150000, 1988));
        list.add(new Employee("Rich", 50000, 1980));
        list.add(new Employee("Andrew", 160000, 1970));
        list.add(new Employee("Ton", 150000, 1958));
        list.add(new Employee("Jose", 40000, 1970));
        list.add(new Employee("Timothy", 50000, 1996));
        list.add(new Employee("Ricardo", 50000, 1988));
        list.add(new Employee("Gemasio", 60000, 1971));
        list.add(new Employee("Mike", 80000, 1992));
    }

Now what i want is to generate the list which do some filtering like: salary > x and salary < y and sort according to the employee name and then again sort if multiple employee have same name but different salary but now using their salary

what I have done so far is :

System.out.println(
                list.stream()
                    .filter(e -> e.getSalary() > 55000)
                    .filter(e -> e.getSalary() < 120000)
                    .sorted(Comparator.comparing(Employee::getName))
                    .collect(Collectors.groupingBy(Employee::getName))
        );

for eg: after sorting only name i got::

<name: Andy salary: 60000 year of birth: 1966>, 
    <name: Gemasio salary: 60000 year of birth: 1971>, 
    <name: Joe salary: 100000 year of birth: 1980>, 
    <name: Mike salary: 90000 year of birth: 1970>, 
    <name: Mike salary: 80000 year of birth: 1992>

here are two mike but now Within this two Mike I want to sort their salary in decendeing form so that new result will be:

<name: Andy salary: 60000 year of birth: 1966>, 
    <name: Gemasio salary: 60000 year of birth: 1971>, 
    <name: Joe salary: 100000 year of birth: 1980>, 
    <name: Mike salary: 80000 year of birth: 1970>, 
    <name: Mike salary: 90000 year of birth: 1992>

and except Mike i dont want to change other orders

but i am not able to get the desired result will anyone please help me out what is wrong or what i need to do to further from here. Thanks :)

2
  • 1
    Is it possible to have two Mikes with same salary (and lets say with different year of birth)? If yes how you want to handle them? Commented Jan 30, 2016 at 21:33
  • yes two employee can have same name and same salary with different dob, it can be managed by the hashcode() Commented Jan 30, 2016 at 21:38

1 Answer 1

5

You are probably looking for

.sorted(Comparator
        .comparing(Employee::getName)         //sort by name
        .thenComparing(Employee::getSalary))  //in case of same names sort by salary

If you want to use descending order you can create separate Comparator which will be comparing based on Employee::getSalary and use its reversed() version like:

        .sorted(Comparator
                .comparing(Employee::getName)
                .thenComparing(
                        Comparator.comparing(Employee::getSalary).reversed()
                )
        )

Possible problem with groupingBy(Employee::getName) is that it returns HashMap which is unordered. If you want to ensure order of keys based on its insertion (and you probably are, otherwise there would be no point in sorting based on name earlier) you could use:

.collect(Collectors.groupingBy(Employee::getName, LinkedHashMap::new, Collectors.toList()));

Demo:

//code creating list
//...

//our code
Map<String, List<Employee>> grouped = list.stream()
        .filter(e -> e.getSalary() > 55000)
        .filter(e -> e.getSalary() < 120000)
        .sorted(Comparator
                .comparing(Employee::getName)
                .thenComparing(
                        Comparator.comparing(Employee::getSalary).reversed()
                )
        )
        .collect(Collectors.groupingBy(Employee::getName, LinkedHashMap::new, Collectors.toList()));

for (Map.Entry<String, List<Employee>> entry : grouped.entrySet()) {
    System.out.println(entry.getKey());
    for (Employee emp : entry.getValue()) {
        System.out.println("\t" + emp);
    }
}

Output:

Andy
    Employee [name=Andy, salary=60000, yearOfBirth=1966]
Gemasio
    Employee [name=Gemasio, salary=60000, yearOfBirth=1971]
Joe
    Employee [name=Joe, salary=100000, yearOfBirth=1980]
Mike
    Employee [name=Mike, salary=90000, yearOfBirth=1970]
    Employee [name=Mike, salary=80000, yearOfBirth=1992]
Sign up to request clarification or add additional context in comments.

2 Comments

Alternatively, you can group into a TreeMap and skip the sorting step…
@Holger True, at least we could skip explicit sorting by name since TreeMap can use natural ordering of key. But we still will need to sort values in list. I was thinking earlier about adding this to answer but decided to let others post it as separate solution (so feel free to do so)

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.