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 -> ...)