[英]How can I filter a List of complex objects so that if two have value for a field, I remove one based on criteria
I have a List of objects, some of which may be similar to others based on a certain field.我有一个对象列表,其中一些可能与基于某个领域的其他对象相似。 In this case, I want to filter one based on the value of another field.
在这种情况下,我想根据另一个字段的值过滤一个。
Here is an example of what I have coming in:这是我进来的一个例子:
[
{
employeeId: 1230,
firstName: "Ronald",
lastName: "McDonald",
device: "Laptop"
},
{
employeeId: 2345,
firstName: "Dennis",
lastName: "Reynolds",
device: "Laptop"
},
{
employeeId: 1230,
firstName: "Ronald",
lastName: "McDonald",
device: "Phone"
}
]
I have 2 objects for Ronald McDonald (employee 1230).我有 2 个对象给 Ronald McDonald(员工 1230)。 I want the Laptop for all employees unless they have a Phone, in which case I just want the phone.
我想要所有员工都使用笔记本电脑,除非他们有电话,在这种情况下,我只想要电话。 So I want to filter out the Ronald McDonald object with
device= "Laptop"
so that my output is as follows:所以我想用
device= "Laptop"
过滤掉 Ronald McDonald 对象,这样我的输出如下:
[
{
employeeId: 1230,
firstName: "Ronald",
lastName: "McDonald",
device: "Phone"
},
{
employeeId: 2345,
firstName: "Dennis",
lastName: "Reynolds",
device: "Laptop"
}
]
Filtering is easy enough, but for whatever reason I can't wrap my head around removing duplicates based on a condition.过滤很容易,但无论出于何种原因,我都无法根据条件删除重复项。
Does any helpful soul have a solution to my situation?是否有任何有用的灵魂可以解决我的情况?
I'm using Java 11, so I have access to Lambda functions, streams, all that good stuff.我使用的是 Java 11,所以我可以访问 Lambda 函数、流以及所有这些好东西。
Edit: My first crack at it is going terribly.编辑:我对它的第一次破解非常糟糕。 I feel like I'm grouping ok, but I can't seem to filter within that group:
我觉得我分组没问题,但我似乎无法在该组内进行过滤:
List<Employee> reducedEmpList = empList.stream()
.collect(Collectors.groupingBy(Employee::getEmployeeId,
// Obviously this is not right:
Collectors.maxBy(Comparator.comparing(Employee::getDevice, (e1, e2) -> {
// Clearly this is not how a comparator works
if("Laptop".equalsIgnoreCase(e1.getDevice()){
return e2;
}
}))));
Iterate through all the employees, and if the device is Phone
search the list for the employee and add to the list entriesToRemove
if another entry exists with that employee and the device is Laptop
:遍历所有员工,如果设备是
Phone
搜索员工列表,如果该员工存在另一个条目并且设备是Laptop
,则将其添加到列表entriesToRemove
:
List<Employee> entriesToRemove = new ArrayList<>();
for(Employee employee : list){
if(employee.getDevice().equals("Phone")){
entriesToRemove.addAll(list.stream().filter(e ->
e.getEmployeeId() == employee.getEmployeeId() && e.getDevice().equals("Laptop"))
.collect(Collectors.toList()));
}
}
Finally remove the entries from the list with removeAll
:最后使用
removeAll
从列表中删除条目:
list.removeAll(entriesToRemove);
System.out.printf(list.toString());
Edit : Solution using Stream API:编辑:使用 Stream API 的解决方案:
List<Employee> reducedEmpList = list.stream()
.collect(Collectors.groupingBy(Employee::getEmployeeId,
Collectors.collectingAndThen(toList(), listPerEmployee ->
listPerEmployee.stream().filter(e -> e.getDevice().equals("Phone")).findFirst()
.map(Collections::singletonList).orElse(listPerEmployee))))
.values().stream().flatMap(Collection::stream).collect(toList());
Output:输出:
[Employee{employeeId=2345, device='Laptop'}, Employee{employeeId=1230, device='Phone'}]
You can use the mergeFunction
of Collectors.toMap
to choose the one with "Phone" as the device when there's more than one:当有多个设备时,您可以使用
Collectors.toMap
的mergeFunction
选择带有“Phone”的设备:
Collection<Employee> filtered = employees.stream().collect(Collectors
.toMap(e -> e.getEmployeeId(), e -> e,
(a, b) -> "Phone".equals(a.getDevice())? a : b,
LinkedHashMap::new)).values();
employees = new ArrayList<>(filtered);
I specified a LinkedHashMap
as the intermediate storage so that any other employees (like Dennis) will remain in their relative positions, if that's important.我指定了一个
LinkedHashMap
作为中间存储,以便任何其他员工(如 Dennis)将保留在他们的相对位置,如果这很重要的话。 If not, you can just use the 3 parameter overload of toMap
and leave that off.如果没有,您可以只使用
toMap
的 3 参数重载并将其关闭。
Note: this assumes that if there is more than one entry for a given employee, one of them always has a device of "Phone".注意:这假设如果给定员工有多个条目,其中一个总是具有“电话”设备。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.