Search code examples
javaarraylistgroovycollections

Find duplicates and remove from ArrayList


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.

  1. If a duplicate id has a status as Complete then keep that object and remove all other object for this id having any other status.
  2. If duplicate id does not have a status as Complete then check for status Pending and keep that and remove any other occurrence for that id in the list.

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?


Solution

  • 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]]'