convert one class object into another using stream

Sanal S :

I know this question can be misleading, if possible someone may correct it, I am not sure how to ask a question with this situation.

I am trying to Convert Class X into Class Y (here class Y contains fields of class X, but in different way, Eg:- Integer a, b; inside class X , converts to Map<a, b> in class Y while other variables stay the same.),

using streams in java 8. I am trying to return the final object to the UI part as json. The project is done in spring boot. Both Class X and Y contains the same objects, but Class Y is to make class X distinct I am not familiar with streams.

Class X

public class X {

private final String thumbnailUrl;
private final Integer duration;
private final String contentId;
private final Date reportDate;
private final Integer count;

public X(Report report, int count) {
    this.thumbnailUrl = report.getContent().getThumbnailUrl();
    this.duration = report.getContent().getDuration();
    this.contentId = report.getContent().getContentId();
    this.reportDate = report.getReportDate();
    this.count = count;
}

public String getThumbnailUrl() {
    return thumbnailUrl;
}

public Integer getDuration() {
    return duration;
}

public String getContentId() {
    return contentId;
}

public Date getReportDate() {
    return reportDate;
}

public Integer getCount() {
    return count;
}    

}

Class Y

public class Y {

private final String thumbnailUrl;
private final Integer duration;
private final String contentId;
private final Map<Date, Integer> contentList;

public Y(X x, Map<Date, Integer> contentList) {
    this.thumbnailUrl = x.getThumbnailUrl();
    this.duration = x.getDuration();
    this.contentId = x.getContentId();
    this.contentList = contentList;
}

public String getThumbnailUrl() {
    return thumbnailUrl;
}

public Integer getDuration() {
    return duration;
}

public String getContentId() {
    return contentId;
}

public Map<Date, Integer> getContentList() {
    return contentList;
}

}

This is what I am currently getting from class X

[
{
    "thumbnailUrl": "a",
    "duration": 12,
    "contentId": "CNT10",
    "reportDate": "2020-01-20",
    "count": 3
},
{
    "thumbnailUrl": "a",
    "duration": 12,
    "contentId": "CNT10",
    "reportDate": "2020-01-21",
    "count": 5
},
{
    "thumbnailUrl": "a",
    "duration": 12,
    "contentId": "CNT10",
    "reportDate": "2020-01-22",
    "count": 3
},
{
    "thumbnailUrl": "a",
    "duration": 12,
    "contentId": "CNT10",
    "reportDate": "2020-01-23",
    "count": 4
}
]

I got the above json in postman after using this code and returning the final list.

List<X> x;
List<Y> y;

x = StreamSupport.stream(reportRepository
                .reportWithRoll(a, b, c).spliterator(), false)
                .map(report -> new X(report, report.getStartCount()))
                .collect(Collectors.toList());

I want this to transformed into content of Class Y as below. How can I achieve this with streams in Java?

[
    {
        "list": [
            {
                "2020-01-20": 3,
                "2020-01-21": 5,
                "2020-01-22": 3,
                "2020-01-23": 4
            }
        ],
        "thumbnailUrl": "a",
        "duration": 12,
        "contentId": "CNT10"
    }
]

I tried this to get the above json format, but ended up getting duplicate data, for single contentId and error for multiple contentId

y = x.stream().map(
                rep -> {
                    Map<Date, Integer> contentList = x.stream().collect(
                            Collectors.toMap(X::getReportDate, X::getCount)
                    );
                    Y yy = new Y(rep, contentList);
                    return yy;
                }
        ).distinct().collect(Collectors.toList());

I am combining the common date and count : key value pair into a single "list" for each unique "contentId" (each unique "contentId" will have its own "thumbnailUrl" and "duration" specific to it, so when I am referring only "contentId" as unique, it will include "thumbnailUrl" and "duration", only the date and count will be multiple for each of these).

Sanal S :

I have found a solution using stream itself, thanks to one stack overflow answer.

y = x.stream()
            .map(X::getContentId)
            .distinct()
            .map(
                    contentId -> {
                        return reportModifier(reportViews, contentId);
                    }
            ).collect(Collectors.toList());


private Y reportModifier(List<x> x, String contentId) {
    Map<Date, Integer> contentList = x.stream()
                                .filter(a -> a.getContentId().equals(contentId))
                                .collect(
                                        Collectors.toMap(X::getReportDate, X::getCount)
                                );

                        X rv = x.stream()
                                .filter(a -> a.getContentId().equals(contentId))
                                .findFirst()
                                .get();

                        Y yy = new Y(rv, contentList);
                        return yy;

}

I got the following json with this

[
{
    "thumbnailUrl": "a",
    "duration": 12,
    "contentId": "CNT10",
    "contentList": {
        "2020-01-21T18:30:00.000+0000": 3,
        "2020-01-20T18:30:00.000+0000": 3,
        "2020-01-22T18:30:00.000+0000": 3,
        "2020-01-19T18:30:00.000+0000": 3
    }
},
{
    "thumbnailUrl": "b",
    "duration": 12,
    "contentId": "CNT12",
    "contentList": {
        "2020-01-19T18:30:00.000+0000": 3
    }
},
{
    "thumbnailUrl": "c",
    "duration": 12,
    "contentId": "CNT11",
    "contentList": {
        "2020-01-21T18:30:00.000+0000": 3,
        "2020-01-20T18:30:00.000+0000": 3,
        "2020-01-19T18:30:00.000+0000": 3
    }
}
]

Guess you like

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