如何在初始使用比较器排序时有条件地颠倒流的顺序?

huangapple go评论62阅读模式
英文:

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&lt;String, Comparator&gt; comparatorsMap = .... // Used to dynamically pull comparators for use

List&lt;InputObject&gt; input = Arrays.asList(new InputObject(&quot;hello&quot;, true), new InputObject(&quot;goodbye&quot;, false));

Comparator&lt;OutputObject&gt; comparator = input.stream()
        .map(comparatorsMap::get)
        .reduce(Comparator::thenComparing)
        .orElse((a, b) -&gt; 0);

List&lt;OutputObject&gt; 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 [ {&quot;byName&quot;, false}, {&quot;byID&quot;, true} ] ):

OutputObject=(&quot;Mike&quot;, 5)
OutputObject=(&quot;Bob&quot;, 4)
OutputObject=(&quot;Mike&quot;, 1)

After first sort (on name):

OutputObject=(&quot;Bob&quot;, 4)
OutputObject=(&quot;Mike&quot;, 5)
OutputObject=(&quot;Mike&quot;, 1)

Then reverse (since ascending == false)

OutputObject=(&quot;Mike&quot;, 5)
OutputObject=(&quot;Mike&quot;, 1)
OutputObject=(&quot;Bob&quot;, 4)

Then after applying the second sort (by ID if tie, and ascending == true)

OutputObject=(&quot;Mike&quot;, 1)
OutputObject=(&quot;Mike&quot;, 5)
OutputObject=(&quot;Bob&quot;, 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` 的比较器。

&gt; 我考虑过在映射 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&lt;OutputObject&gt; comparator = input.stream()
        .map(in -&gt; {
          Comparator&lt;OutputObject&gt; c = comparatorsMap.get(in.inputName);
          return in.ascending ? c : c.reversed();
        })
        .reduce(Comparator::thenComparing)
        .orElse((a, b) -&gt; 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 -&gt; new AbstractMap.SimpleEntry&lt;&gt;(comparatorsMap.get(in.inputName), in.ascending))
    .map(e -&gt; e.getValue() ? e.getKey() : e.getKey().reversed())
    ...

but I think that's far less easy to understand.

huangapple
  • 本文由 发表于 2023年2月23日 23:27:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75546897.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定