Reputation: 49
I have an ArrayList of Device objects. I want to remove duplicate entries.
The device objects has three fields: id, name, and status. If an id occurs multiple times, I need to check the status of each duplicate id and filter it based on the below criteria.
There can be 3 status i.e. New, Pending, Complete.
Device class -:
class Device {
long id
String name
String status
@Override
String toString() {
return "Device [${Id}, ${status}]"
}
}
Sample data:
[
[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']
]
Expected output:
[
[id : 11, name:'test', status:'pending'],
[id : 13, name : 'abc', status:'new'],
[id : 14, name : 'xyz', status:'pending'],
[id : 15, name : 'wxy', status:'complete'],
]
Can someone here help with this logic possibly in Groovy or else in Java?
Upvotes: 1
Views: 350
Reputation: 20699
I would use Groovy's groupBy
/sort
combo to achieve what you want:
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]]'
Upvotes: 1
Reputation: 19545
This may be resolved by building a map by device.id and implementing the merge function with the custom logic.
The device statuses may be ordered using an enum/map, so the device with "higher" status is kept while merging.
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);
Output:
Device [11, test, pending]
Device [13, abc, new]
Device [14, xyz, pending]
Device [15, wxy, complete]
Upvotes: 1