0

I have the following class Person -

Person.java -

public class Person {
    private int id;
    private String department;
    private double salary;

    public Person(int id, String department, double salary) {
        this.id = id;
        this.department = department;
        this.salary = salary;
    }

    public String getDepartment() {
        return department;
    }

    public double getSalary() {
        return salary;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", department='" + department + '\'' +
                ", salary=" + salary +
                '}';
    }
}

It has the fields -

id, department, salary

Now I have first predicate -

Predicate<List<Person>> hasSalaryOf40k = list -> {
            boolean myReturn = false;
            Iterator<Person> iterator = list.iterator();
            while (iterator.hasNext()) {
                Person person = iterator.next();
                double salary = person.getSalary();
                if (salary == 40000) {
                    myReturn = true;
                    break;
                }
            }
            return myReturn;
        };

Here, I want to filter out those lists having persons with salary as 40K.

Second predicate -

Predicate<List<Person>> isDeveloper = list -> {
            boolean myReturn = false;
            Iterator<Person> iterator = list.iterator();
            while (iterator.hasNext()) {
                Person person = iterator.next();
                String department = person.getDepartment();
                if (department.equals("Developer")) {
                    myReturn = true;
                    break;
                }
            }
            return myReturn;
        };

Here, I want to filter out those lists having persons with department as 'developer'

Third predicate -

Predicate<List<Person>> hasSalaryOf40kAndIsDeveloper = list ->
                hasSalaryOf40k.and(isDeveloper).test(list);

Here, I want to filter out those lists having persons with both salary as 40K and department as "developer"

Now I have the following two lists -

List<Person> list1 = new ArrayList<>(List.of(
                new Person(1, "Developer", 35000),
                new Person(2, "Accountant", 40000),
                new Person(3, "Clerk", 20000),
                new Person(4, "Manager", 50000)
        ));

        List<Person> list2 = new ArrayList<>(List.of(
                new Person(1, "Developer", 40000),
                new Person(2, "Accountant", 35000),
                new Person(3, "Clerk", 22000),
                new Person(4, "Manager", 55000)
        ));

The list1 does not match the desired criteria while list2 matches the desired criteria.

Now I call the predicate method test -

System.out.println(hasSalaryOf40kAndIsDeveloper.test(list1));
System.out.println(hasSalaryOf40kAndIsDeveloper.test(list2));

Output -

true
true

Desired output -

false
true

Where am I going wrong and how to correct my code?

Payel Senapati
  • 1,134
  • 1
  • 11
  • 27
  • Predicate does not filter the list, it just spits out a boolean value. Here you are in fact testing if (`there is any person has salary of 40 K` AND `there is any person is developer`) . That's why it is true. – Ricky Mo Jun 01 '22 at 01:53
  • List 1 meets the criteria of your predicate because it contains a developer AND contains a person whose salary is 40000. There's nothing in your code that requires that the developer and the 40k-earner have to be the same person. – Dawood ibn Kareem Jun 01 '22 at 01:55
  • 1
    You might be interested in [How to filter a Java Collection (based on predicate)?](https://stackoverflow.com/questions/122105/how-to-filter-a-java-collection-based-on-predicate) – Ricky Mo Jun 01 '22 at 01:57
  • 1
    Side notes: `list -> hasSalaryOf40k.and(isDeveloper).test(list)` is redundant. Just use `hasSalaryOf40k.and(isDeveloper)`. Further, whatever textbook you’re using, you should replace it with something more up-to-date. There is no reason to deal with an `Iterator` here. Instead of `Iterator iterator = list.iterator(); while (iterator.hasNext()) { Person person = iterator.next(); /* code */ }` you should just use `for(Person person: list) { /* code */ }`. – Holger Jun 01 '22 at 10:43

1 Answers1

2

You're applying the predicate to the whole list and not each element of the list, so it's true that the list contains a developer and its true that the list contains a salary over 40k. You need to apply the predicate to the Person object rather than the List<Person> object

Quinn
  • 7,072
  • 7
  • 39
  • 61