英文:
How to conditionally reverse the order of a stream where I'm using comparators to sort initially?
问题
Comparator<OutputObject> comparator = input.stream()
.map(inputObj -> inputObj.ascending ? comparatorsMap.get(inputObj.inputName) : comparatorsMap.get(inputObj.inputName).reversed())
.reduce(Comparator::thenComparing)
.orElse((a, b) -> 0);
List<OutputObject> sorted = dataCollection.stream().sorted(comparator).collect(Collectors.toList());
英文:
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.
答案1
得分: 2
我觉得你可能在找这样的东西:
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);
这根据 `ascending` 标志条件性地反转了来自 `comparatorsMap` 的比较器。
> 我考虑过在映射 lambda 中可能保存一个布尔字段,并在不同的 lambda 中利用它
你可以这样做:
input.stream()
.map(in -> new AbstractMap.SimpleEntry<>(comparatorsMap.get(in.inputName), in.ascending))
.map(e -> e.getValue() ? e.getKey() : e.getKey().reversed())
...
但我觉得那样不太容易理解。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论