How to get parent object based on child object fields

Viewed 2134

Parent Class :

public class Person {
    String firstName;
    String lastName;
    Long id;
    List<Phone> phoneNumber = new ArrayList<>();
    int age;

    public Person(String firstName, String lastName, int age, Long id, List<Phone> phone) {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.id = id;
        this.phoneNumber = phone;
    }

Child Phone object (1st level) :

public class Phone {
    String number;
    String type;
    Long id;
    public Phone(String number, String type, Long id) {
        super();
        this.number = number;
        this.type = type;
        this.id = id;
    }
}

I am trying to fetch person object whose phone object type is home and its number should contain "888" in it.

List<Phone> list = personList.stream().map(p -> p.getPhoneNumber().stream()).
                flatMap(inputStream -> inputStream).filter(p -> p.number.contains("888") && p.type.equals("HOME")).collect(Collectors.toList());

        System.out.println(list.toString());

From above stream code, I am able to get phone object. But how to get parent object of that phone object in that same function itself ?.

I tried in this way and I am getting null for non-matched objects.

List<Person> finalList = personList.stream().map( per -> {
            List<Phone> phones = per.getPhoneNumber();
            Optional<Phone> ph = phones.stream().filter(p -> p.number.contains("888") && p.type.equals("HOME")).findAny();
        if(ph.isPresent())
            return per;
        return null;
        }).collect(Collectors.toList());
1 Answers
List<Person> result = personList.stream()
    .filter( person -> person.phoneNumber.stream()
                             .anyMatch(phone -> phone.type.equals("HOME") && 
                                                phone.number.contains("888"))
    .collect(Collectors.toList());

The thing you were looking for is stream of phones. It'll do the trick.

Having people with their phones, you can now remove those phones that don't match the criteria.

List<Person> result = personList.stream()
        .filter( person -> person.phoneNumber.stream()
                                 .anyMatch(phone -> phone.type.equals("HOME") && 
                                                    phone.number.contains("888"))
        .map(person -> {
            List<Phone> phones = person.phoneNumber.stream()
                                    .filter(phone -> phone.type.equals("HOME") && 
                                                    phone.number.contains("888"))
                                    .collect(Collectors.toList());
            return new Person(person.firstName, person.lastName, person.age, person.id, phones);
        })
        .collect(Collectors.toList());
Related