Search code examples
javajava-stream

How to get a specific child object with Java streams


Alrighty: I've been banging my head on a wall the whole day and can't solve this issue. I am trying to find an ID in an object list which is like 3 levels down the hierarchy with the Java stream API. I know how to do it with a for loop but I need to get it with a stream.

JSON response is:

{
    "NumberOfOwners": 1,
    "CurrentPage": 1,
    "TotalItems": 1,
    "TotalPages": 1,
    "PageSize": 1,
    "PageItems": [
        {
            "Id": 1560,
            "Title": "PlsWrk",
            "IsSubmitted": true,
            "Owner": {
                "Branch": null,
                "Position": null,
                "Id": null,
                "FirstName": null,
                "LastName": null,
                "ParentName": null,
                "Gender": null,
                "Image": null,
                "LoginStatusId": 0,
                "EmployeeStatus": 0,
                "CompanyName": null,
                "IsSubcontractor": false
            },
            "KeyResults": [
                {
                    "Id": 5032,
                    "Title": "asdf1",
                    "OverallStatus": 2,
                    "MonthKeyResults": [
                        {
                            "Id": 12484,
                            "Month": 9,
                            "Status": 3,
                            "Progress": "REaplace1"
                        },
                        {
                            "Id": 12483,
                            "Month": 8,
                            "Status": 3,
                            "Progress": "sadf4"
                        },
                        {
                            "Id": 12482,
                            "Month": 7,
                            "Status": 1,
                            "Progress": "On Track1"
                        }
                    ]
                },
                {
                    "Id": 5033,
                    "Title": "asdf2",
                    "OverallStatus": 1,
                    "MonthKeyResults": [
                        {
                            "Id": 12485,
                            "Month": 7,
                            "Status": 2,
                            "Progress": "Recovery2"
                        },
                        {
                            "Id": 12487,
                            "Month": 9,
                            "Status": 2,
                            "Progress": "asdfreas"
                        },
                        {
                            "Id": 12486,
                            "Month": 8,
                            "Status": 1,
                            "Progress": "asdf5"
                        }
                    ]
                },
                {
                    "Id": 5034,
                    "Title": "asdf3",
                    "OverallStatus": 2,
                    "MonthKeyResults": [
                        {
                            "Id": 12490,
                            "Month": 9,
                            "Status": 1,
                            "Progress": "asdafa"
                        },
                        {
                            "Id": 12489,
                            "Month": 8,
                            "Status": 2,
                            "Progress": "asdf6"
                        },
                        {
                            "Id": 12488,
                            "Month": 7,
                            "Status": 3,
                            "Progress": "Replace3"
                        }
                    ]
                }
            ]
        }
    ]
}

Precisely I want stream to return the MonthyKeyResult object with a specific ID.

At the moment, I am here:

public static MonthKeyResults getOkrMonthlyProgressById(PageItems okr, Integer monthlyProgressId){

    //here i get KeyResults object list
    List<KeyResults> keyResult = okr.getKeyResults().stream().collect(Collectors.toList());
        
    //and now I am trying to get all MonthKeyResults 
    //objects but I not doing it right
    List<MonthKeyResults> monthKeyResults = keyResult.stream().
               filter(monthKeyResult -> monthKeyResult.
                          getMonthKeyResults().
                          stream().collect(Collectors.toList()));
    
    //and then I am thinking of going through the monthKeyResults 
    //list with stream and finding Id I need and returning that 
    //whole object with something like this
    MonthKeyResults mKeyResults = monthKeyResults.stream().filter(id -> id.getId().
                    equals(monthlyProgressId)).findAny().orElse(null);
    return mKeyResult;
}

I've got one more question:

I've separated getting the final object as you see in 3 streams; is it possible to get it in one go or you need to separate the objects like this and go through them separately?


Solution

  • Probably you're looking for something like:

    return okr.getKeyResults().stream()
            .flatMap(keyResult -> keyResult.getMonthKeyResults().stream())
            .filter(monthKeyResult -> monthKeyResult.getId().equals(monthlyProgressId))
            .findAny()
            .orElse(null);