Java面试:对日志记录实现分组

问题

  • 我们已获得一个应用程序日志列表,其中包含 id、消息、标签和日期时间等属性。
  • 我们的任务是按创建的日期时间对这些日志进行划分分组。 

例子:

[ApplicationLog[id=c1e1838c-1c17-4e22-a476-c604dc3dadcc, message=Logs 1, tags=[tag-1, server-4, tag-1], date=Sat Sep 16 21:48:36 EDT 2023], ApplicationLog[id=ca1f45ec-8444-4cb5-8695-08147519080f, message=Logs 2, tags=[data-1, server-1, data-2], date=Sun Sep 10 21:48:36 EDT 2023], ApplicationLog[id=d93a32c1-1e11-4155-992c-1ea70052f3c0, message=Logs 3, tags=[tag-1, tag-4, data-1], date=Mon Sep 18 21:48:36 EDT 2023], 
.....

划分后输出结果:

2023-09-19:[ApplicationLog[id=794fe57d-5d92-4bc3-ab62-11e9aa2d7640, message=Logs 6, tags=[server-2, server-3, data-4], date=Tue Sep 19 21:48:36 EDT 2023], ApplicationLog[id=f58b6c6f-bcd9-4cbd-9f56-e73ac951a1ac, message=Logs 21, tags=[tag-4, tag-4, tag-2], date=Tue Sep 19 21:48:36 EDT 2023], ....]
2023-09-17:[ApplicationLog[id=e531feff-8da8-4155-8b3d-87fea2f1fd33, message=Logs 37, tags=[tag-1, tag-1, server-1], date=Sun Sep 17 21:48:36 EDT 2023],...] 
....

解决方案
1、处理输入数据

  • 对于输入数据,我们将创建一个 Java 记录类 dto。

public record ApplicationLog(String id, String message, List<String> tags, Date date) {
}

  • 对于记录 dto,我们使用 Random 方法构造每个属性。

  Common common = new Common();
 List<ApplicationLog> applicationLogs = common.getSampleLogs();

common的getSampleLogs方法:

 public List<ApplicationLog> getSampleLogs(){
        return IntStream.rangeClosed(1,100)
            .mapToObj(this::toApplicationLogs)
            .toList();
    }

    private ApplicationLog toApplicationLogs(int i) {
        List<String> tags = List.of("server-1", "tag-1","data-1","server-2", "tag-2","data-2", "server-3", "server-4", "tag-4","data-4");
        List<Integer> nWeeks = List.of(1,2,3,4,5,6,7,8,9,10);
        return new ApplicationLog(
            UUID.randomUUID().toString(),
           
"Logs "+i,
            getTags(tags),
            Date.from(
                ZonedDateTime
                    .now()
                    .minusDays(
                        nWeeks.get(new Random().nextInt(nWeeks.size()))
                    )
                .toInstant()
            )
        );
    }

2、解决主体方案:

  • 我们的解决方案流式传输输入数据并使用日期字段对记录进行分组。
  • 由于我们的日期是日期时间格式,因此我们需要将其转换为yyyy-MM-dd。
  • 对于记录分组,我们可以使用Collectors API提供的groupingBy方法。

public class PartitionData {

    public static void main(String[] args) {
        Common common = new Common();
        List<ApplicationLog> applicationLogs = common.getSampleLogs();//制造数据

        Map<String, List<ApplicationLog>> groupedLogs = applicationLogs.stream()
            .collect(
                Collectors.groupingBy(log -> {
                    SimpleDateFormat formatter = new SimpleDateFormat(
"yyyy-MM-dd");
                    return formatter.format(log.date());
                }
            ));

        groupedLogs.forEach((key, value) -> System.out.println(key +
":" + value));
    }
}

现在我们可以打印日期和分组日志作为输出。