1

I have a list of Map objects that look something like this:

year => 2016, month => 10, day => 11, count => 123 

I have an element for every day in the range of startDate < endDate.

I want to be able to reduce these elements into different temporal groupings based on the interval between startDate and endDate. If the difference between startDate and endDate is greater than 4 years, I want to group them into years. If the difference is less than four years, but greater than a year, I want to group them into months. If it's less than a year, but greater than a month, I want to group into weeks. Anything less than a month, no grouping necessary.

When I say "group" I mean I want to sum up the count elements for everything that belongs to a particular year (using the first example above), and return a single map for each year that looks like this:

year => 2016, month => 1 day => 1 count => 9897 

I know there must be an elegant way to accomplish this, but I'm having a difficult time wrapping my brain around the logic.

5
  • 6
    If the difference is between 1 and 4 years, you say you want to group the elements by month, but how? I.e. if you have 2 years of data eg. 2015 and 2016, do you want all elements from i.e. January into one group, no matter the year, or do you want separate groups for January, 2015 and January, 2016? Same question for weeks, etc. Commented Aug 2, 2017 at 20:59
  • 7
    Show us some effort - what have you tried so far? Commented Aug 2, 2017 at 21:09
  • @FedericoPeraltaSchaffner I basically want to "roll up" everything into a single element for the entire year, month or week. Commented Aug 3, 2017 at 16:59
  • @daniel0mullins but what if you have entries for the same month in different years? Commented Aug 3, 2017 at 17:22
  • 1
    @FedericoPeraltaSchaffner I mean to say roll up everything for that year, month or day. Not just an arbitrary month. A "month" is identified by it's year and month. In other words, August 2017 -- not just "August" Commented Aug 4, 2017 at 18:02

2 Answers 2

2

I don't get it, you could simply do:

if(starDate is smaller then endDate by 4 year) { resultMap = yourList.stream() .collect(Collectors.groupingBy(map.get("year"), Collectors.summingInt(map.get("count"))); } else if(starDate is... another condition) { resultMap = yourList.stream() .collect(Collectors.groupingBy(map.get("month"), Collectors.summingInt(map.get("count"))); } // all the there cases... 

Later map this result to whatever you want.

Sign up to request clarification or add additional context in comments.

Comments

2

Just use Collectors.groupingBy as usual and supply the classifier that you want.

final LocalDate endDate = dateCounts.last().getDate(); Function<DateCount, LocalDate> mapLocalDate = dc-> { LocalDate ld = dc.getDate(); long m = Period.between(ld, endDate ).toTotalMonths(); if ( m > 4*12 ) { return ld.withMonth(1).withDayOfMonth(1); } else if ( m >= 1 ) { return ld.withDayOfMonth(1); } else { return ld; } }; Map<LocalDate, Long> r = dateCounts.stream() .collect(Collectors.groupingBy( mapLocalDate, TreeMap::new, Collectors.summingLong(DateCount::getCount) ) ); System.out.println( "EndDate = " + endDate ); System.out.println( r ); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.