Andrey Durow February 2016

Creation of custom comparator for map in groovy

I have class in groovy

class WhsDBFile {
    String name
    String path
    String svnUrl
    String lastRevision
    String lastMessage
    String lastAuthor
}

and map object

def installFiles = [:]

that filled in loop by

WhsDBFile dbFile = new WhsDBFile()
installFiles[svnDiffStatus.getPath()] = dbFile

now i try to sort this with custom Comparator

        Comparator<WhsDBFile> whsDBFileComparator = new Comparator<WhsDBFile>() {
            @Override
            int compare(WhsDBFile o1, WhsDBFile o2) {
                if (FilenameUtils.getBaseName(o1.name) > FilenameUtils.getBaseName(o2.name)) {
                    return 1
                } else if (FilenameUtils.getBaseName(o1.name) > FilenameUtils.getBaseName(o2.name)) {
                    return -1
                }
                return 0
            }
        }
        installFiles.sort(whsDBFileComparator);

but get this error java.lang.String cannot be cast to WhsDBFile

Any idea how to fix this? I need to use custom comparator, cause it will be much more complex in the future.

p.s. full source of sample gradle task (description of WhsDBFile class is above):

    project.task('sample') << {
        def installFiles = [:]
        WhsDBFile dbFile = new WhsDBFile()
        installFiles['sample_path'] = dbFile
        Comparator<WhsDBFile> whsDBFileComparator = new Comparator<WhsDBFile>() {
            @Override
            int compare(WhsDBFile o1, WhsDBFile o2) {
                if (o1.name > o2.name) {
                    return 1
                } else if (o1.name > o2.name) {
                    return -1
                }
                return 0
            }
        }
        installFiles.sort(whsDBFileComparator);
    }

Answers


Jérémie B February 2016

You can try to sort the entrySet() :

def sortedEntries = installFiles.entrySet().sort { entry1, entry2 -> 
  entry1.value <=> entry2.value 
}

you will have a collection of Map.Entry with this invocation. In order to have a map, you can then collectEntries() the result :

def sortedMap = installFiles.entrySet().sort { entry1, entry2 -> 
      ... 
}.collectEntries()


dmahapatro February 2016

sort can also take a closure as parameter which coerces to a Comparator's compare() method as below. Usage of toUpper() method just mimics the implementation of FilenameUtils.getBaseName().

installFiles.sort { a, b -> 
    toUpper(a.value.name) <=> toUpper(b.value.name)
}

// Replicating implementation of FilenameUtils.getBaseName()
// This can be customized according to requirement 
String toUpper(String a) {
    a.toUpperCase()
}

Post Status

Asked in February 2016
Viewed 2,356 times
Voted 10
Answered 2 times

Search




Leave an answer