I have code as such, which selects and chains comparators:
class InputObject { String inputName; String ascending; }
Map<String, Comparator> comparatorsMap = .... // Used to dynamically pull comparators for use
List<InputObject> input = Arrays.asList(new InputObject("hello", true), new InputObject("goodbye", false));
Comparator<OutputObject> comparator = input.stream()
.map(comparatorsMap::get)
.reduce(Comparator::thenComparing)
.orElse((a, b) -> 0);
List<OutputObject> sorted = dataCollection.stream().sorted( comparator ).collect( Collectors.toList() );
I'd like to use the ascending
field from InputObject as a conditional to determine if it should reverse the collection, but I'm not sure how to achieve that. Note that each input object has its own ascending
field, so these would have to be intermediate actions.
So example:
Unsorted (input stream is [ {"byName", false}, {"byID", true} ]
):
OutputObject=("Mike", 5)
OutputObject=("Bob", 4)
OutputObject=("Mike", 1)
After first sort (on name):
OutputObject=("Bob", 4)
OutputObject=("Mike", 5)
OutputObject=("Mike", 1)
Then reverse (since ascending == false
)
OutputObject=("Mike", 5)
OutputObject=("Mike", 1)
OutputObject=("Bob", 4)
Then after applying the second sort (by ID if tie, and ascending == true
)
OutputObject=("Mike", 1)
OutputObject=("Mike", 5)
OutputObject=("Bob", 4)
I thought about potentially saving a boolean field within the map lambda and leveraging that in a different lambda, but I'm not sure how you can apply the action of reversing the stream / collection conditionally.
I think you're looking for something like this:
Comparator<OutputObject> comparator = input.stream()
.map(in -> {
Comparator<OutputObject> c = comparatorsMap.get(in.inputName);
return in.ascending ? c : c.reversed();
})
.reduce(Comparator::thenComparing)
.orElse((a, b) -> 0);
This conditionally reverses the comparator from comparatorsMap
, based on the ascending
flag.
I thought about potentially saving a boolean field within the map lambda and leveraging that in a different lambda
You could do it like this:
input.stream()
.map(in -> new AbstractMap.SimpleEntry<>(comparatorsMap.get(in.inputName), in.ascending))
.map(e -> e.getValue() ? e.getKey() : e.getKey().reversed())
...
but I think that's far less easy to understand.