查找重复项并从 ArrayList 中删除

Find duplicates and remove from ArrayList

我有一个设备对象的 ArrayList。我想删除重复的条目。

设备对象有三个字段:id、name、status。如果一个 id 出现多次,我需要检查每个重复 id 的状态并根据以下条件过滤它。

可以有 3 种状态,即新的、待定的、完成的。

  1. 如果重复 ID 的状态为“完成”,则保留该对象并删除具有任何其他状态的此 ID 的所有其他对象。
  2. 如果重复 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]]'