简体   繁体   中英

Java 8 Map a List to another list and count

I am looking to create a list of history values for an existing list so that I can save it in DB to be displayed later in a table

Class Data {
  Date date;
  int int1;
  int int2;
}

class DataHistory {
  Date date;
   int sum_Int1_beforeOrEqualDate;
   int sum_Int2_beforeOrEqualDate;
   String someOtherValues;
}

For example I have several lines perDate with all values. What I would like to achieve is :

My input :

date,    int1,  int2
01/01/18,  2,    3
01/01/18,  0,    1
02/01/18,  0,    1
02/01/18,  3,    0
03/01/18,  1,    3
...

My output :

date,    sum_Int1_beforeOrEqualDate,  sum_Int2_beforeOrEqualDate
01/01/18,  2,    4
02/01/18,  3,    1
03/01/18,  1,    3
...

I have tried several things, mainly with Map, but has never been able to do it with List-->List.

What I have tried to do is :

Edit: My lastAttempt, which clearly shows I don't know what i am doing..

List<OutputList> outputList =
inputlist
.stream()
.map( e -> new DataHistory())
.collect(Collectors.groupingBy(int1));

I believe you're trying to simply sum the values grouping by date. So assuming you have parsed data as a List

List<Data> list = getDataAsList();
List<DataHistory> historyList = list.stream()
            .collect(Collectors.groupingBy(data -> data.date)).entrySet().stream()
            .map((entry) -> {
                DataHistory history = new DataHistory();
                history.date = entry.getKey();
                List<Data> dataList = entry.getValue();
                history.sum_Int1_beforeOrEqualDate = dataList.stream().mapToInt(data -> data.int1).sum();
                history.sum_Int2_beforeOrEqualDate = dataList.stream().mapToInt(data -> data.int2).sum();
                return history;
            })
            .collect(Collectors.toList());

Tell me if I got the logic correct.

You can accomplish the task at hand using the toMap collector:

Collection<DataHistory> resultSet = 
         myList.stream()
               .collect(Collectors.toMap(Data::getDate,
                        e -> new DataHistory(e.getDate(), e.getInt1(), e.getInt2(), null),
                        DataHistory::merge)).values();

This assumes you have a constructor defined as follows in your DataHistory class:

public DataHistory(Date date, int sum_Int1_beforeOrEqualDate, 
          int sum_Int2_beforeOrEqualDate, String someOtherValues) {
        this.date = date;
        this.sum_Int1_beforeOrEqualDate = sum_Int1_beforeOrEqualDate;
        this.sum_Int2_beforeOrEqualDate = sum_Int2_beforeOrEqualDate;
        this.someOtherValues = someOtherValues;
}

and a merge function defined as such:

public DataHistory merge(DataHistory other){
        this.sum_Int1_beforeOrEqualDate += other.getSum_Int1_beforeOrEqualDate();
        this.sum_Int2_beforeOrEqualDate += other.getSum_Int2_beforeOrEqualDate();
        return this;
}

in the DataHistory class.


Further, if you explicitly require a List<DataHistory> as opposed to a Collection<DataHistory> then you can do:

 List<DataHistory> historyList = new ArrayList<>(resultSet); 

Note that I am passing null to the DataHistory constructor for the fourth parameter simply because I don't know what data to pass, so I'll leave that for you to decide upon.

What you could do is use Collections.reducing which works pretty good.

List<DataHistory> dataHistories = 
                   list.stream()
                       .collect(Collectors.groupingBy(Data::getDate, 
                                Collectors.reducing(DataHistory::new,
                                                    DataHistoryHelper::merge)))
                       .values();

This solution assumes you have a constructor in DataHistory taking a Data as parameter.

public DataHistory(Data o) {
    this.date = o.getDate();
    // and so on
}

And that you have a method (anywhere) that takes care of merging two DataHistory objects

public DataHistory merge(DataHistory o1, DataHistory o2) {
    DataHistory merged = new DataHistory();
    merged.setSum_Int1_beforeOrEqualDate(o1.getSum_Int1_beforeOrEqualDate + o2.getSum_Int1_beforeOrEqualDate);
    // and so on
    return merged;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM