Home > Software engineering >  Chaining with AlphanumComparator for Java TreeSet
Chaining with AlphanumComparator for Java TreeSet

Time:11-07

I'm using AlphanumComparator from Using the AlphanumComparator. I'm having trouble figuring out how to chain additional comparators to it.

I have an object called NodeInstance. I want to sort on 2 fields. definitionId is an enum whose toString is an alphanumeric field. displayOrder is an int.

Tried something like this

Comparator<NodeInstance> comparator = ((s1, s2) -> new AlphanumComparator()
    .compare(((NodeInstance) s1).getDefinitionId().toString(), ((NodeInstance) s2).getDefinitionId().toString()))
    .thenComparingInt(NodeInstance::getDisplayOrder);

but IntelliJ warns me that Inconvertible types; cannot cast '<lambda parameter>' to NodeInstane.

I cannot figure out the correct syntax to get this to work.

I'm trying to use this in a TreeSet, so ultimately I want to be able to do `new TreeSet<>(comparator);

CodePudding user response:

AlphanumComparator is a regular implementation of the Comparator interface, therefore instead of messing with compare() inside the lambda, you need to leverage fluent static methods of the comparator.

I think you're looking for Comparator.comparing(keyExtractor, keyComparator), which expects a function extracting a sort key from the argument, and a Comparator which should be used to compare sort keys.

Where key extractor function would the following lambda expression:

(NodeInstance node) -> node.getDefinitionId().toString()

And an instance of the AlphanumComparator would serve as a key comparator.

Comparator<NodeInstance> comparator =
    Comparator.comparing(
        (NodeInstance node) -> node.getDefinitionId().toString(),
        new AlphanumComparator()
    )
    .thenComparingInt(NodeInstance::getDisplayOrder);

Explicit type in the lambda expression is required to correctly because it can't be correctly inferred based on the target type of the aggregated Comparator.

Alternatively, instead of specifying the type in the lambda, you can use a so-called type-witness Comparator.<NodeInstance,String>comparing(node -> ...)

  • Related