When as Set is not what you want

When you want to filter out duplicates in a list in groovy you normally do something like:

        def list = [2, 1, 2, 3]
        def filtered = list as Set
        assertEquals([1, 2, 3], filtered as List)

This kicks out all duplicates in a one-liner. But what if the list is sorted (e.g. in reverseOrder)?

        def list = [3, 2, 2, 1]
        def filtered = list as Set
        assertEquals([3, 2, 1], filtered as List) // this fails!

One solution would be to use a small closure:

        def list = [3, 2, 2, 1]
        def filteredList = []
        list.each {
            if (!filteredList.contains(it)) {
                filteredList << it
            }
        }
        assertEquals([3, 2, 1], filteredList)

This closures preserves the order and filters out the duplicates.

2 Responses to “When as Set is not what you want”

  1. Chris Broadfoot Says:

    Just use List#unique()

    groovy:000> [3, 2, 2, 1].unique()
    ===> [3, 2, 1]

  2. Nils Kassube Says:

    Well, just be aware that List#unique() is destructive. This can cause subtle bugs if you call unique on a method parameter.

Leave a Reply