¿Es posible agrupar por los últimos 15 días usando Collectors.groupingBy de Java?
Aporte:
public class Tweet { String id; LocalDate createdAt; // Constructor Ignored List<Tweet> tweets = new ArrayList(){{ add(new Tweet("1", "2021-11-17")); add(new Tweet("2", "2021-11-16")); add(new Tweet("3", "2021-11-14")); add(new Tweet("4", "2021-11-13")); add(new Tweet("5", "2021-11-12")); add(new Tweet("7", "2021-10-09")); add(new Tweet("8", "2021-10-08")); add(new Tweet("9", "2021-10-07")); add(new Tweet("10", "2021-09-02")); add(new Tweet("11", "2021-09-01")); ... }}; }Rendimiento esperado:
2021-11-17: (group must include 2021-11-17 + 15 days before 17th) Tweet("1", "2021-11-17"); Tweet("2", "2021-11-16"); Tweet("3", "2021-11-14"); Tweet("4", "2021-11-13"); Tweet("5", "2021-11-12"); 2021-10-09: (group to include 2021-10-09 + 15 days before 9th) Tweet("7", "2021-10-09"); Tweet("8", "2021-10-08"); Tweet("9", "2021-10-07"); 2021-09-01: (group to include 2021-09-01 + 15 days before 1st) Tweet("10", "2021-09-02"); Tweet("11", "2021-09-01");Lógica actual ( no funciona ):
Método principal:
TemporalAdjusters adjuster = TemporalAdjusters.ofDateAdjuster(d -> d.minusDays(15)); Map<LocalDate, List<Tweets>> groupByLast15Days = tweets.stream() .collect(Collectors.groupingBy(item -> item.createdAt()) .with(adjuster))); System.out.println(groupByLast15Days); // provides incorrect results¡cualquier ayuda es enormemente apreciada! ¡Gracias!
Puede obtener la diferencia de días entre dos LocalDateTime usando ChronoUnit.DAYS.between(from,to) como se indica aquí .
Luego puede dividir esto por 15 (para que tenga el mismo número para todos los días en ese rango):
LocalDate origin=LocalDate.now(); Map<LocalDate, List<Tweets>> groupByLast15Days = tweets.stream() .collect(Collectors.groupingBy(item-> Long.valueOf(ChronoUnit.DAYS.between(item.createdAt(),origin)/15));Si desea agrupar por la fecha de inicio, puede invertir el cálculo (mientras que la diferencia entre los 15 días se elimina mediante la división entera):
LocalDate origin=LocalDate.now(); Map<LocalDate, List<Tweets>> groupByLast15Days = tweets.stream() .collect(Collectors.groupingBy(item -> origin.plusDays( (ChronoUnit.DAYS.between(origin, item.createdAt()) /15)*15 ) )); Si desea utilizar TemporalAdjusters , puede hacerlo así:
LocalDate origin=LocalDate.now(); TemporalAdjusters adjuster = TemporalAdjusters.ofDateAdjuster(d -> origin.plusDays( (ChronoUnit.DAYS.between(origin, d) /15)*15 ) );Explicaciones :
Dividir un entero por otro entero siempre da como resultado un entero, incluso si el cociente tuviera decimales. La división de enteros simplemente elimina esos lugares decimales. Si divide un número por 15, obtendrá el mismo resultado para 15 números consecutivos. Después de volver a multiplicarlo por 15, obtendrías el primero de esos 15 números. Dividir un número por 15 y volverlo a multiplicar por 15 tiene como finalidad que cada 15 números consecutivos se asigne al mismo número (el primero de esos 15).
ChronoUnit.DAYS.between(date1, date2) solo calcula el número de días entre date1 y date2 .