Java 8 Lambda: Map List<Object[]> (List of Object Arrays) to List<Bean>

gene b. :

I receive a List of Object arrays,

List<Object[]> rawRows = service.getRows();

Any particular value can be obtained as e.g.

(Date)((Object[])rawRows.get(i))[3]  // In each item, Array Element #3 is a certain Date

I need to map this to a List<Report> for a POJO which has specific fields defined for each value:

public class Report {
    private String abbreviation;
    private String username;
    private Integer recallid;
    private Date recalldate;
    // ... + getters/setters   

    // Constructor
    public Report (String abbreviation, String username, Integer recallid, Date recalldate, ...)
    {
    }
}

I'm stumped on the following: How would I specify the index in this Lamba expression to map to my new List<Report>?

List<Report> detailReports =  rawRows.stream().map(obj -> new Report(
            (String)((Object[])rawRows.get(0))[0], // I'm hard-coding (0) but need "i"
            (String)((Object[])rawRows.get(0))[1], // I'm hard-coding (0) but need "i"
            (Integer)((Object[])rawRows.get(0))[2],// I'm hard-coding (0) but need "i"
            (Date)((Object[])rawRows.get(0))[3],   // I'm hard-coding (0) but need "i"
            //...
                           )).collect(Collectors.toList());             

My goal is to have a List<Report> with all the array elements mapped to the POJO per object exactly per the specified sequence. But there's no i index for me to track. In this example I'm hard-coding 0 as the rawRow to get from the original List.

MyStackRunnethOver :

First, change your lambda from

obj -> new Report((String)((Object[])rawRows.get(0))[0] ...

to

obj -> new Report((String) obj[0] ...

obj is the lambda parameter, and in the map() function will take on the value of each item in rawRows.

Next, I would really recommend converting the lambda into a separate, named function. This would have signature public Report rawRowToReport(Object[] rawRow) and would hold all your indexing logic, instead of writing it in the lambda body.

The reason for this is, as you've noticed, "there's no i index for me to track": this is because the indexing being done by i is into the raw row itself. It's really just the deserialization logic for whatever is in the Object[]. This sort of logic should be encapsulated in its own method (or ideally class) which only deals with serializing and/or deserializing. Outside users (like your Stream) delegate the nitty gritty to that class or method. Ultimately, the Stream only handles the process of iterating over the data and applying filters and transforms. It doesn't know what those filters and transforms require.

rawRows.stream().map(this::rawRowToReport).collect(Collectors.toList());

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=415947&siteId=1