从具有相同成员的列表中过滤对象
Filter objects from a list that have the same member
我有一个对象列表。对象看起来像这样:
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;
...
}
我需要找到具有相同 agendaCode
、visitTypeCode
和 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());
但它并没有按照我的预期进行。理想情况下,我会有一个列表列表,其中每个子列表都是共享相同 agendaCode
、visitTypeCode
和 scheduledTime
的 Slots 对象的列表。我在函数式编程方面苦苦挣扎,所以任何帮助或指示都会很棒!
这是Java11,我也在用vavr。
最简单的方法是定义一个新的 class,其中包含必要的字段(agendaCode
、visitTypeCode
和 scheduledTime
)。不要忘记 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()));
您也可以仅在 Visits
中为 agendaCode
、visitTypeCode
和 scheduledTime
实现 equals
方法。在这种情况下,通过 s.getVisit()
使用 groupingBy
我爱。不过,我不喜欢创建新的 class 或定义新的 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
.[=16 使用的比较方法=]
请注意,您应该存储在某处或使用一种方法来定义要分组的字段。
既然你提到你正在使用 vavr,这里是解决这个问题的 vavr 方法。
假设您有io.vavr.collection.List
(或Array
或Vector
或Stream
或类似的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()
)
)
);
你要分组的字段都是字符串。您可以定义一个函数来连接这些字段值并将其用作您的组的键。示例
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));
我有一个对象列表。对象看起来像这样:
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;
...
}
我需要找到具有相同 agendaCode
、visitTypeCode
和 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());
但它并没有按照我的预期进行。理想情况下,我会有一个列表列表,其中每个子列表都是共享相同 agendaCode
、visitTypeCode
和 scheduledTime
的 Slots 对象的列表。我在函数式编程方面苦苦挣扎,所以任何帮助或指示都会很棒!
这是Java11,我也在用vavr。
最简单的方法是定义一个新的 class,其中包含必要的字段(agendaCode
、visitTypeCode
和 scheduledTime
)。不要忘记 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()));
您也可以仅在 Visits
中为 agendaCode
、visitTypeCode
和 scheduledTime
实现 equals
方法。在这种情况下,通过 s.getVisit()
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
.[=16 使用的比较方法=]
请注意,您应该存储在某处或使用一种方法来定义要分组的字段。
既然你提到你正在使用 vavr,这里是解决这个问题的 vavr 方法。
假设您有io.vavr.collection.List
(或Array
或Vector
或Stream
或类似的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()
)
)
);
你要分组的字段都是字符串。您可以定义一个函数来连接这些字段值并将其用作您的组的键。示例
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));