import java.util.*;
import java.util.stream.*;
public class FileRecordExample {
public static void main(String[] args) {
// 1. Sample data
List<FileRecord> records = Arrays.asList(
new FileRecord("2025", "07", "Taipei"),
new FileRecord("2025", "07", "Kaohsiung"),
new FileRecord("2025", "07", "Taipei"),
new FileRecord("2025", "07", "Tainan"),
new FileRecord("2025", "07", "Taoyuan"),
new FileRecord("2025", "07", "Hsinchu"),
new FileRecord("2025", "07", "Taichung"),
new FileRecord("2025", "06", "Taichung"),
new FileRecord("2025", "06", "Hsinchu")
);
// 2–5. Pipeline:
// 2) group by "yyyyMM" → Map<String,List<String>>
// 3) sort keys descending
// 4) for each: calculate count & limited locations & displayYyyymm
// 5) collect into List<Map<String,Object>>
List<Map<String, Object>> result = records.stream()
.collect(Collectors.groupingBy(
r -> r.getYyyy() + r.getMm(),
Collectors.mapping(FileRecord::getLocation, Collectors.toList())
))
.entrySet().stream()
.sorted(Map.Entry.<String, List<String>>comparingByKey(Comparator.reverseOrder()))
.map(entry -> {
String yyyymm = entry.getKey();
List<String> allLocs = entry.getValue();
int totalCount = allLocs.size();
List<String> limited = allLocs.stream()
.limit(6)
.collect(Collectors.toList());
Map<String,Object> map = new HashMap<>();
map.put("yyyymm", yyyymm);
map.put("displayYyyymm", yyyymm.substring(0,4) + "-" + yyyymm.substring(4));
map.put("locations", limited);
map.put("count", totalCount);
return map;
})
.collect(Collectors.toList());
// 6. Print out:
result.forEach(m -> System.out.println(
"(" +
m.get("yyyymm") + ", " +
m.get("displayYyyymm") + ", " +
m.get("locations") + ", " +
"count=" + m.get("count") +
")"
));
}
}
aW1wb3J0IGphdmEudXRpbC4qOwoKaW1wb3J0IGphdmEudXRpbC5zdHJlYW0uKjsKCgoKcHVibGljIGNsYXNzIEZpbGVSZWNvcmRFeGFtcGxlIHsKCiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7CgogICAgICAgIC8vIDEuIFNhbXBsZSBkYXRhCgogICAgICAgIExpc3Q8RmlsZVJlY29yZD4gcmVjb3JkcyA9IEFycmF5cy5hc0xpc3QoCgogICAgICAgICAgICBuZXcgRmlsZVJlY29yZCgiMjAyNSIsICIwNyIsICJUYWlwZWkiKSwKCiAgICAgICAgICAgIG5ldyBGaWxlUmVjb3JkKCIyMDI1IiwgIjA3IiwgIkthb2hzaXVuZyIpLAoKICAgICAgICAgICAgbmV3IEZpbGVSZWNvcmQoIjIwMjUiLCAiMDciLCAiVGFpcGVpIiksCgogICAgICAgICAgICBuZXcgRmlsZVJlY29yZCgiMjAyNSIsICIwNyIsICJUYWluYW4iKSwKCiAgICAgICAgICAgIG5ldyBGaWxlUmVjb3JkKCIyMDI1IiwgIjA3IiwgIlRhb3l1YW4iKSwKCiAgICAgICAgICAgIG5ldyBGaWxlUmVjb3JkKCIyMDI1IiwgIjA3IiwgIkhzaW5jaHUiKSwKCiAgICAgICAgICAgIG5ldyBGaWxlUmVjb3JkKCIyMDI1IiwgIjA3IiwgIlRhaWNodW5nIiksCgogICAgICAgICAgICBuZXcgRmlsZVJlY29yZCgiMjAyNSIsICIwNiIsICJUYWljaHVuZyIpLAoKICAgICAgICAgICAgbmV3IEZpbGVSZWNvcmQoIjIwMjUiLCAiMDYiLCAiSHNpbmNodSIpCgogICAgICAgICk7CgoKCiAgICAgICAgLy8gMuKAkzUuIFBpcGVsaW5lOgoKICAgICAgICAvLyAgMikgZ3JvdXAgYnkgInl5eXlNTSIg4oaSIE1hcDxTdHJpbmcsTGlzdDxTdHJpbmc+PgoKICAgICAgICAvLyAgMykgc29ydCBrZXlzIGRlc2NlbmRpbmcKCiAgICAgICAgLy8gIDQpIGZvciBlYWNoOiBjYWxjdWxhdGUgY291bnQgJiBsaW1pdGVkIGxvY2F0aW9ucyAmIGRpc3BsYXlZeXl5bW0KCiAgICAgICAgLy8gIDUpIGNvbGxlY3QgaW50byBMaXN0PE1hcDxTdHJpbmcsT2JqZWN0Pj4KCiAgICAgICAgTGlzdDxNYXA8U3RyaW5nLCBPYmplY3Q+PiByZXN1bHQgPSByZWNvcmRzLnN0cmVhbSgpCgogICAgICAgICAgICAuY29sbGVjdChDb2xsZWN0b3JzLmdyb3VwaW5nQnkoCgogICAgICAgICAgICAgICAgciAtPiByLmdldFl5eXkoKSArIHIuZ2V0TW0oKSwKCiAgICAgICAgICAgICAgICBDb2xsZWN0b3JzLm1hcHBpbmcoRmlsZVJlY29yZDo6Z2V0TG9jYXRpb24sIENvbGxlY3RvcnMudG9MaXN0KCkpCgogICAgICAgICAgICApKQoKICAgICAgICAgICAgLmVudHJ5U2V0KCkuc3RyZWFtKCkKCiAgICAgICAgICAgIC5zb3J0ZWQoTWFwLkVudHJ5LjxTdHJpbmcsIExpc3Q8U3RyaW5nPj5jb21wYXJpbmdCeUtleShDb21wYXJhdG9yLnJldmVyc2VPcmRlcigpKSkKCiAgICAgICAgICAgIC5tYXAoZW50cnkgLT4gewoKICAgICAgICAgICAgICAgIFN0cmluZyB5eXl5bW0gPSBlbnRyeS5nZXRLZXkoKTsKCiAgICAgICAgICAgICAgICBMaXN0PFN0cmluZz4gYWxsTG9jcyA9IGVudHJ5LmdldFZhbHVlKCk7CgogICAgICAgICAgICAgICAgaW50IHRvdGFsQ291bnQgPSBhbGxMb2NzLnNpemUoKTsKCiAgICAgICAgICAgICAgICBMaXN0PFN0cmluZz4gbGltaXRlZCA9IGFsbExvY3Muc3RyZWFtKCkKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAubGltaXQoNikKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY29sbGVjdChDb2xsZWN0b3JzLnRvTGlzdCgpKTsKCgoKICAgICAgICAgICAgICAgIE1hcDxTdHJpbmcsT2JqZWN0PiBtYXAgPSBuZXcgSGFzaE1hcDw+KCk7CgogICAgICAgICAgICAgICAgbWFwLnB1dCgieXl5eW1tIiwgICAgICAgICAgeXl5eW1tKTsKCiAgICAgICAgICAgICAgICBtYXAucHV0KCJkaXNwbGF5WXl5eW1tIiwgICB5eXl5bW0uc3Vic3RyaW5nKDAsNCkgKyAiLSIgKyB5eXl5bW0uc3Vic3RyaW5nKDQpKTsKCiAgICAgICAgICAgICAgICBtYXAucHV0KCJsb2NhdGlvbnMiLCAgICAgICBsaW1pdGVkKTsKCiAgICAgICAgICAgICAgICBtYXAucHV0KCJjb3VudCIsICAgICAgICAgICB0b3RhbENvdW50KTsKCiAgICAgICAgICAgICAgICByZXR1cm4gbWFwOwoKICAgICAgICAgICAgfSkKCiAgICAgICAgICAgIC5jb2xsZWN0KENvbGxlY3RvcnMudG9MaXN0KCkpOwoKCgogICAgICAgIC8vIDYuIFByaW50IG91dDoKCiAgICAgICAgcmVzdWx0LmZvckVhY2gobSAtPiBTeXN0ZW0ub3V0LnByaW50bG4oCgogICAgICAgICAgICAiKCIgKwoKICAgICAgICAgICAgbS5nZXQoInl5eXltbSIpICsgIiwgIiArCgogICAgICAgICAgICBtLmdldCgiZGlzcGxheVl5eXltbSIpICsgIiwgIiArCgogICAgICAgICAgICBtLmdldCgibG9jYXRpb25zIikgKyAiLCAiICsKCiAgICAgICAgICAgICJjb3VudD0iICsgbS5nZXQoImNvdW50IikgKwoKICAgICAgICAgICAgIikiCgogICAgICAgICkpOwoKICAgIH0KCn0K