查找重复项并从 ArrayList 中删除
Find duplicates and remove from ArrayList
我有一个设备对象的 ArrayList。我想删除重复的条目。
设备对象有三个字段:id、name、status。如果一个 id 出现多次,我需要检查每个重复 id 的状态并根据以下条件过滤它。
可以有 3 种状态,即新的、待定的、完成的。
- 如果重复 ID 的状态为“完成”,则保留该对象并删除具有任何其他状态的此 ID 的所有其他对象。
- 如果重复 ID 的状态不是 Complete,则检查状态 Pending 并保留该状态,并删除列表中该 ID 的任何其他匹配项。
设备class-:
class Device {
long id
String name
String status
@Override
String toString() {
return "Device [${Id}, ${status}]"
}
}
示例数据:
[
[id : 11, name:'test', status:'pending'],
[id : 13, name : 'abc', status:'new'],
[id : 14, name : 'xyz', status:'pending'],
[id : 11, name : 'test', status:'new'],
[id : 15, name : 'wxy', status:'complete'],
[id : 15, name : 'wxy', status:'pending']
]
预期输出:
[
[id : 11, name:'test', status:'pending'],
[id : 13, name : 'abc', status:'new'],
[id : 14, name : 'xyz', status:'pending'],
[id : 15, name : 'wxy', status:'complete'],
]
这里有人可以在 Groovy 或 Java 中帮助解决这个逻辑问题吗?
这可以通过device.id构建地图并使用自定义逻辑实现合并功能来解决。
可以使用 enum/map 对设备状态进行排序,因此在合并时保留“较高”状态的设备。
Map<String, Integer> statusOrder = Map.of(
"new", 1,
"pending", 2,
"complete", 3
);
List<Device> devices = Arrays.asList(
new Device(11, "test", "pending"),
new Device(13, "abc", "new"),
new Device(14, "xyz", "pending"),
new Device(11, "test", "new"),
new Device(15, "wxy", "complete"),
new Device(15, "wxy", "pending")
);
devices
.stream()
.collect(Collectors.toMap(
Device::getId,
d -> d,
(d1, d2) -> statusOrder.get(d1.status)
>= statusOrder.get(d2.status) ? d1 : d2,
LinkedHashMap::new
))
.values()
.forEach(System.out::println);
输出:
Device [11, test, pending]
Device [13, abc, new]
Device [14, xyz, pending]
Device [15, wxy, complete]
我会使用 Groovy 的 groupBy
/sort
组合来实现你想要的:
class Device {
long id
String name
String status
@Override
String toString() { "Device [$id, $status]" }
}
def devices = [
[id : 11, name:'test', status:'pending'],
[id : 13, name : 'abc', status:'new'],
[id : 14, name : 'xyz', status:'pending'],
[id : 11, name : 'test', status:'new'],
[id : 15, name : 'wxy', status:'complete'],
[id : 15, name : 'wxy', status:'pending']
].collect{ it as Device }
def result = devices.groupBy{ it.id }.findResults{ id, devs ->
devs.sort{ [ 'complete', 'pending', 'new' ].indexOf it.status }.first()
}
assert result.toString() == '[Device [11, pending], Device [13, new], Device [14, pending], Device [15, complete]]'
我有一个设备对象的 ArrayList。我想删除重复的条目。
设备对象有三个字段:id、name、status。如果一个 id 出现多次,我需要检查每个重复 id 的状态并根据以下条件过滤它。
可以有 3 种状态,即新的、待定的、完成的。
- 如果重复 ID 的状态为“完成”,则保留该对象并删除具有任何其他状态的此 ID 的所有其他对象。
- 如果重复 ID 的状态不是 Complete,则检查状态 Pending 并保留该状态,并删除列表中该 ID 的任何其他匹配项。
设备class-:
class Device {
long id
String name
String status
@Override
String toString() {
return "Device [${Id}, ${status}]"
}
}
示例数据:
[
[id : 11, name:'test', status:'pending'],
[id : 13, name : 'abc', status:'new'],
[id : 14, name : 'xyz', status:'pending'],
[id : 11, name : 'test', status:'new'],
[id : 15, name : 'wxy', status:'complete'],
[id : 15, name : 'wxy', status:'pending']
]
预期输出:
[
[id : 11, name:'test', status:'pending'],
[id : 13, name : 'abc', status:'new'],
[id : 14, name : 'xyz', status:'pending'],
[id : 15, name : 'wxy', status:'complete'],
]
这里有人可以在 Groovy 或 Java 中帮助解决这个逻辑问题吗?
这可以通过device.id构建地图并使用自定义逻辑实现合并功能来解决。
可以使用 enum/map 对设备状态进行排序,因此在合并时保留“较高”状态的设备。
Map<String, Integer> statusOrder = Map.of(
"new", 1,
"pending", 2,
"complete", 3
);
List<Device> devices = Arrays.asList(
new Device(11, "test", "pending"),
new Device(13, "abc", "new"),
new Device(14, "xyz", "pending"),
new Device(11, "test", "new"),
new Device(15, "wxy", "complete"),
new Device(15, "wxy", "pending")
);
devices
.stream()
.collect(Collectors.toMap(
Device::getId,
d -> d,
(d1, d2) -> statusOrder.get(d1.status)
>= statusOrder.get(d2.status) ? d1 : d2,
LinkedHashMap::new
))
.values()
.forEach(System.out::println);
输出:
Device [11, test, pending]
Device [13, abc, new]
Device [14, xyz, pending]
Device [15, wxy, complete]
我会使用 Groovy 的 groupBy
/sort
组合来实现你想要的:
class Device {
long id
String name
String status
@Override
String toString() { "Device [$id, $status]" }
}
def devices = [
[id : 11, name:'test', status:'pending'],
[id : 13, name : 'abc', status:'new'],
[id : 14, name : 'xyz', status:'pending'],
[id : 11, name : 'test', status:'new'],
[id : 15, name : 'wxy', status:'complete'],
[id : 15, name : 'wxy', status:'pending']
].collect{ it as Device }
def result = devices.groupBy{ it.id }.findResults{ id, devs ->
devs.sort{ [ 'complete', 'pending', 'new' ].indexOf it.status }.first()
}
assert result.toString() == '[Device [11, pending], Device [13, new], Device [14, pending], Device [15, complete]]'