首页 > 解决方案 > 使用 Java 比较器按另一个列表对对象列表进行排序

问题描述

有两个输入列表如下:

inputA = [
            {
               name: "A",
               age: 20
            }, 
            {
               name: "B",
               age: 30
            },
            {  name: "C",
               age: 25
            },
            {  name: "D",
               age: 28
            }
          ]

inputB = ["D", "B"]

我的首选输出列表必须如下:

expectedOutput = [
            {
               name: "D",
               age: 28
            }, 
            {
               name: "B",
               age: 30
            },
            {  name: "A",
               age: 20
            },
            {  name: "C",
               age: 25
            }
          ]

到目前为止我所做的如下所示:

AtomicInteger count = new AtomicInteger();
Collections.sort(inputA, Comparator
    .comparing(a -> 
    if (inputB.indexOf(a.getName()) > -1) {
        return -1;
    }
    else {
        return count.incrementAndGet();
    })
    .thenComparingInt(a -> a.getAge()));

我得到的输出如下

actualOutput = [
            {
               name: "D",
               age: 28
            }, 
            {
               name: "B",
               age: 30
            },
            {  name: "C",
               age: 25
            },
            {  name: "A",
               age: 20
            }
          ]

问题在于列表中没有名称的元素inputB。那里的订单没有原始订单inputA。为了使原始订单持续存在{ name: "A", age: 20 },应该先于{ name: "C", age: 25 }

使用比较器链接策略时如何解决此问题?

更新 排序逻辑是,如果 inputA 具有名称等于 inputB 列表的对象,则这些元素应位于 inputA 的顶部,然后这些元素必须按其年龄排序,同时保持 inputA 中其他元素的原始顺序inputB 中不存在的

这不可能是重复的,因为这个问题试图比较两个列表,并通过第一个列表中的对象的属性对公共元素进行排序,同时将其余元素保留在原始顺序中。

标签: javalambdajava-8java-streamcomparator

解决方案


正如我所看到的,如果名称包含在inputB列表中,则需要按年龄对元素进行排序,如果列表中不包含其他元素,则保持原样inputB。按年龄排序的元素应该出现在结果的顶部,而未排序的元素应该出现在底部。

如果这是您需要做的,您可以使用Comparator.comparingInt并让它返回一个整数,即年龄(对于第一种情况)或Integer.MAX_VALUE(对于另一种情况)。

您应该优化 check over inputB,使其快速。为此,您可以创建一个HashSetfrom inputB

这是代码:

Set<String> set = new HashSet<>(inputB);

Collections.sort(inputA, Comparator.comparingInt(a -> set.contains(a.getName()) ? 
                                                      a.getAge() : 
                                                      Integer.MAX_VALUE));

只要您的年龄不等于Integer.MAX_VALUE.

这个想法是你总是按年龄比较,但如果一个元素不属于inputB,你把年龄变成Integer.MAX_VALUE。这会有两个效果:第一,它会使不包含在的元素inputB出现在底部;其次,正如您总是返回一样Integer.MAX_VALUE,列表的顺序inputA被保留,因为Collections.sort实现了稳定的排序


推荐阅读