5

我有一个对象列表。该对象如下所示:

public class Slots {
  String slotType;
  Visits visit;
}


public class Visits {
  private long visitCode;
  private String agendaCode;
  private String scheduledTime;
  private String resourceType;
  private String resourceDescription;
  private String visitTypeCode;
  ...
}

我需要找到具有相同元素的元素,agendaCodevisitTypeCode对于scheduledTime我的生活,我无法完成它。

我试过这个:

Set<String> agendas = slotsResponse.getContent().stream()
    .map(Slots::getVisit)
    .map(Visits::getAgendaCode)
    .collect(Collectors.toUnmodifiableSet());

Set<String> visitTypeCode = slotsResponse.getContent().stream()
    .map(Slots::getVisit)
    .map(Visits::getVisitTypeCode)
    .collect(Collectors.toUnmodifiableSet());

Set<String> scheduledTime = slotsResponse.getContent().stream()
    .map(Slots::getVisit)
    .map(Visits::getScheduledTime)
    .collect(Collectors.toUnmodifiableSet());

List<Slots> collect = slotsResponse.getContent().stream()
    .filter(c -> agendas.contains(c.getVisit().getAgendaCode()))
    .filter(c -> visitTypeCode.contains(c.getVisit().getVisitTypeCode()))
    .filter(c -> scheduledTime.contains(c.getVisit().getScheduledTime()))
    .collect(Collectors.toList());

但它并没有像我想象的那样做。理想情况下,我会有一个列表列表,其中每个子列表都是共享相同的 Slots 对象的列表agendaCodevisitTypeCode并且scheduledTime. 我在函数式编程中挣扎,所以任何帮助或指针都会很棒!

这是 Java 11,我也在使用 vavr。

4

4 回答 4

3

既然你提到你正在使用 vavr,这是解决这个问题的 vavr 方法。

假设您有您的io.vavr.collection.List(或Array或或VectorStream或类似的 vavr 集合)访问:

List<Visits> visits = ...;

final Map<Tuple3<String, String, String>, List<Visits>> grouped =
    visits.groupBy(visit ->
        Tuple.of(
            visit.getAgendaCode(),
            visit.getVisitTypeCode(),
            visit.getScheduledTime()
        )
    );

java.util.List访问:

List<Visits> visits = ...;

Map<Tuple3<String, String, String>, List<Visits>> grouped = visits.stream().collect(
    Collectors.groupingBy(
        visit ->
            Tuple.of(
                visit.getAgendaCode(),
                visit.getVisitTypeCode(),
                visit.getScheduledTime()
            )
    )
);
于 2019-02-22T15:24:12.357 回答
1

我喜欢Ruslan 使用 Collectors::groupingBy 的想法。不过,我不喜欢创建新类或定义新equals方法。他们都强迫你使用一个Collectors::groupingBy版本。如果要在其他方法中按其他字段分组怎么办?

这是一段可以让您克服此问题的代码:

slotsResponse.getContent()
    .stream()
    .collect(Collectors.groupingBy(s -> Arrays.asList(s.getVisit().getAgendaCode(), s.getVisit().getVisitTypeCode(), s.getVisit().getScheduledTime())))
    .values();

我的想法是为每个需要的字段(agendaCode、visitTypeCode、scheludedTime)创建一个新容器,并比较这些新创建的容器上的插槽。我本来希望用一个简单的Object数组这样做,但它不起作用 - 数组应该与 Arrays.equals 进行比较,这不是Collectors::groupingBy.

请注意,您应该存储在某处或使用一种方法来定义要分组的字段。

于 2019-02-22T14:58:37.773 回答
1

您要分组的字段都是字符串。您可以定义一个函数来连接这些字段值并将其用作您的组的键。例子

Function<Slots,String> myFunc = s -> s.getVisit().agendaCode + s.getVisit().visitTypeCode + s.getVisit().scheduledTime;
                               // or s.getVisit().agendaCode +"-"+ s..getVisit().visitTypeCode +"-"+ s.getVisit().scheduledTime;

然后分组如下:

Map<String,List<Slots>> result = slotsResponse.getContent().stream()
                               .collect(Collectors.groupingBy(myFunc));
于 2019-02-22T15:31:06.813 回答
1

最简单的方法是定义一个包含必需字段(agendaCodevisitTypeCodescheduledTime的新类。别忘了equals/hashcode

public class Visits {
    private long visitCode;
    private String resourceType;
    private String resourceDescription;
    private Code code;
    ...
}
class Code {
    private String agendaCode;
    private String scheduledTime;
    private String visitTypeCode;
    ...
    @Override
    public boolean equals(Object o) {...}
    @Override
    public int hashCode() {...}
}

然后你可以groupingBy像这样使用:

Map<Code, List<Slots>> map = slotsResponse.getContent().stream()
            .collect(Collectors.groupingBy(s -> s.getVisit().getCode()));

你也可以只在equals内部实现方法,和。在这种情况下,由VisitsagendaCodevisitTypeCodescheduledTimegroupingBys.getVisit()

于 2019-02-22T14:12:25.197 回答