使用 Stream API 查找相同日期并计算对象

问题描述 投票:0回答:2

我需要一些有关 Stream API 的帮助。我需要根据位置对对象列表进行分组,如果位置相同但日期不同(无论时间如何),则将计数增加 1。 我为带有 getter setter 和数据以及预期输出的类提供了以下代码。

public class Event {
    String location;
    String date;
    String count; 
 
    public String getCount() {
        return count;
    }

    public void setCount(String count) {
        this.count = count;
    }
    public String getLocation() {
        return location;
    }

    public String getDate() {
        return date;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public void setDate(String date) {
        this.date = date;
    }
} 

事件类数据:

Event event = new Event();
        
event.setLocation("98.55.62.162");
event.setDate("09/17/2022 12:05:43 PM");
event.add(event);

event.setLocation("98.55.62.162");
event.setDate("09/16/2022 12:05:45 PM");
event.add(event);

event.setLocation("98.55.62.162");
event.setDate("09/16/2022 12:05:47 PM");
event.add(event);

event.setLocation("98.55.62.162");
event.setDate("09/15/2022 12:05:49 PM");
event.add(event);

event.setLocation("98.55.62.163");
event.setDate("09/17/2022 12:05:31 PM");
event.add(event);

event.setLocation("98.55.62.163");
event.setDate("09/16/2022 12:05:22 PM");
event.add(event);

event.setLocation("98.55.62.163");
event.setDate("09/16/2022 12:05:11 PM");
event.add(event);

我试着做

Map<String, List<Event>>

Map<String, List<Event>> eventMap = events.stream().collect(Collectors.groupingBy(s -> s.getLocation()));

这对我不起作用。
我需要像这样的输出 Map 地图,其中字符串是位置,计数基于日期。如果日期不同,则将计数增加 1。时间在这里并不重要。 我不知道如何使用流 API 或 for 循环对它们进行分组。

o/p: ["98.55.62.162":3 , "98.55.62.163":2]
java collections java-stream distinct-values
2个回答
2
投票

这个答案基于 Demian 的答案。我做了以下更改:

  1. Locale.ENGLISH
    DateTimeFormatter
    一起使用,这对于您的日期时间值不是强制的,但强烈建议使用,因为日期时间格式化/解析 API 是
    Locale
    敏感的。
  2. Event#date
    的类型保留为
    String
    ,同时我建议您使用
    LocalDateTime
    并在构造
    Event
    对象时解析字符串日期时间字符串,就像 Demian 在他的答案中所做的那样。如果您有单独的日、月、年、小时、分钟等值,则可以使用
    LocalDateTime#of
    方法之一来填充
    Event#date
  3. .map(e -> LocalDateTime.parse(e.getDate(), formatter).toLocalDate())
    的使用:在此映射中,我首先将
    Event#date
    解析为
    LocalDateTime
    ,然后使用
    LocalDateTime#toLocalDate
  4. 仅提取日期部分
List<Event> events = new ArrayList<>();

Event event = new Event();
event.setLocation("98.55.62.162");
event.setDate("09/17/2022 12:05:43 PM");
events.add(event);

...
...
...

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a", Locale.ENGLISH);

Map<String, Long> eventMap = events
        .stream()
        .collect(
                Collectors.groupingBy(Event::getLocation))
        .entrySet()
        .stream()
        .collect(Collectors.toMap(
                Map.Entry::getKey, v -> v.getValue()
                        .stream()
                        .map(e -> LocalDateTime.parse(e.getDate(), formatter).toLocalDate())
                        .distinct()
                        .count()));

System.out.println(eventMap);

输出

{98.55.62.163=2, 98.55.62.162=3}

Trail:日期时间了解有关 现代日期时间 API 的更多信息。


2
投票

这是可能的,但有点棘手。检查一下:

Event event = new Event();
List<Event> events = new ArrayList<>();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/d/yyyy hh:mm:ss a");

event.setLocation("98.55.62.162");
event.setDate(LocalDate.parse("09/17/2022 12:05:43 PM", formatter));
events.add(event);

event = new Event();
event.setLocation("98.55.62.162");
event.setDate(LocalDate.parse("09/16/2022 12:05:45 PM", formatter));
events.add(event);

event = new Event();
event.setLocation("98.55.62.162");
event.setDate(LocalDate.parse("09/16/2022 12:05:47 PM", formatter));
events.add(event);

event = new Event();
event.setLocation("98.55.62.162");
event.setDate(LocalDate.parse("09/15/2022 12:05:49 PM", formatter));
events.add(event);

event = new Event();
event.setLocation("98.55.62.163");
event.setDate(LocalDate.parse("09/17/2022 12:05:31 PM", formatter));
events.add(event);

event = new Event();
event.setLocation("98.55.62.163");
event.setDate(LocalDate.parse("09/16/2022 12:05:22 PM", formatter));

events.add(event);

event = new Event();
event.setLocation("98.55.62.163");
event.setDate(LocalDate.parse("09/16/2022 12:05:11 PM", formatter));
events.add(event);

Map<String, Long> eventMap = events
        .stream()
        .collect(
                Collectors.groupingBy(Event::getLocation)
        ).entrySet()
        .stream()
        .collect(Collectors.toMap(
                Map.Entry::getKey, v -> v.getValue()
                        .stream()
                        .map(e -> e.getDate())
                        .distinct()
                        .count()));
© www.soinside.com 2019 - 2024. All rights reserved.