如何使用Java 8对每日Keyword列表执行groupBy分组与Collect收集操作?
Hey there! Let's break down how to use Java 8's Stream API to group and collect your Keyword list effectively. Since each keyword has a daily record, here are some common grouping scenarios you might need, with practical code examples:
1. Group by Keyword Name (get all daily records per keyword)
This is the most straightforward use case: group all records under their respective keyword names, so you can easily access every daily entry for a specific keyword.
import java.util.List; import java.util.Map; import java.util.stream.Collectors; // Assume we have a List<Keyword> keywords initialized with your data Map<String, List<Keyword>> keywordsByName = keywords.stream() .collect(Collectors.groupingBy(Keyword::getName)); // Usage example: fetch all daily records for "kw1" List<Keyword> kw1DailyRecords = keywordsByName.get("kw1");
2. Group by Metric Day (get all keywords for a specific day)
If you want to view all keyword records from a particular date, group by the metricDay field. A quick note: since java.util.Date includes timestamp details, if your metricDay is meant to be a date-only value, convert it to LocalDate first to avoid accidental grouping by time differences.
// Group directly by Date (watch out for time components) Map<Date, List<Keyword>> keywordsByMetricDay = keywords.stream() .collect(Collectors.groupingBy(Keyword::getMetricDay)); // Better approach: convert Date to LocalDate to group by calendar date only import java.time.LocalDate; import java.time.ZoneId; private static LocalDate convertToLocalDate(Date date) { return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); } Map<LocalDate, List<Keyword>> keywordsByCalendarDay = keywords.stream() .collect(Collectors.groupingBy(kw -> convertToLocalDate(kw.getMetricDay())));
3. Nested Grouping: Keyword Name → Metric Day
For a hierarchical view—first grouped by keyword name, then by metric day—you can nest groupingBy collectors. This lets you quickly access a specific keyword's record on a specific day.
Map<String, Map<LocalDate, Keyword>> keywordDailyLookup = keywords.stream() .collect(Collectors.groupingBy( Keyword::getName, Collectors.toMap( kw -> convertToLocalDate(kw.getMetricDay()), Function.identity(), (existing, newRecord) -> newRecord // Handle duplicates (keep latest if needed) ) )); // Usage example: get "kw1" record on 11/11/1999 Keyword kw1On19991111 = keywordDailyLookup.get("kw1").get(LocalDate.of(1999, 11, 11));
4. Aggregate Data While Grouping
Instead of just collecting records, you might want to compute statistics for each keyword—like the highest price, average position, or latest record. Here are a few useful examples:
Get the highest price per keyword
Map<String, Double> maxPricePerKeyword = keywords.stream() .collect(Collectors.groupingBy( Keyword::getName, Collectors.mapping( Keyword::getPrice, Collectors.maxBy(Double::compareTo) ) )) .entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, entry -> entry.getValue().orElse(0.0) // Fallback if no records exist for a keyword ));
Get the average position per keyword
Map<String, Double> avgPositionPerKeyword = keywords.stream() .collect(Collectors.groupingBy( Keyword::getName, Collectors.averagingDouble(Keyword::getPosition) ));
Get the latest (most recent metricDay) record per keyword
Map<String, Keyword> latestRecordPerKeyword = keywords.stream() .collect(Collectors.groupingBy( Keyword::getName, Collectors.collectingAndThen( Collectors.maxBy((kw1, kw2) -> kw1.getMetricDay().compareTo(kw2.getMetricDay())), Optional::get ) ));
内容的提问来源于stack exchange,提问作者Josemy

