提问人:coconut 提问时间:2/22/2019 最后编辑:Mikhail Kholodkovcoconut 更新时间:2/23/2019 访问量:579
从列表中筛选具有相同成员的对象
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());
但它并没有像我想象的那样做。理想情况下,我会有一个列表列表,其中每个子列表都是共享相同 和 的 Slots 对象列表。我在函数式编程方面很挣扎,所以任何帮助或指导都会很棒!agendaCode
visitTypeCode
scheduledTime
这是 Java 11,我也在使用 vavr。
答:
最简单的方法是定义一个包含必需品字段 (和 ) 的新类。别忘了.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()));
此外,您只能在 和 中实现方法。在本例中,请使用equals
Visits
agendaCode
visitTypeCode
scheduledTime
groupingBy
s.getVisit()
我喜欢 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)创建一个新容器,并比较这些新创建的容器上的插槽。我本来想用一个简单的数组来做到这一点,但它不起作用 - 数组应该与 Arrays.equals 进行比较,这不是 .Object
Collectors::groupingBy
请注意,您应该存储在某个位置或使用一种方法来定义要按哪些字段进行分组。
既然你提到你正在使用 vavr,这里是解决这个问题的 vavr 方法。
假设您有(或或类似的 vavr 集合)访问:io.vavr.collection.List
Array
Vector
Stream
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));
评论
myFunc
List<Slots>
Visits
Slots
result
s.agendaCode + s.visitTypeCode + s.scheduledTime
result.get
myFunc
Slot
上一个:将列表中的所有项目相互相减
下一个:按重复次数排序
评论
filter