使用Java Comparators按另一个List对对象列表进行排序

sim*_*enz 8 java lambda comparator java-8 java-stream

Thare是两个输入列表,如下所示:

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

inputB = ["D", "B"]
Run Code Online (Sandbox Code Playgroud)

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

expectedOutput = [
            {
               name: "D",
               age: 28
            }, 
            {
               name: "B",
               age: 30
            },
            {  name: "A",
               age: 20
            },
            {  name: "C",
               age: 25
            }
          ]
Run Code Online (Sandbox Code Playgroud)

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

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()));
Run Code Online (Sandbox Code Playgroud)

我得到的输出如下

actualOutput = [
            {
               name: "D",
               age: 28
            }, 
            {
               name: "B",
               age: 30
            },
            {  name: "C",
               age: 25
            },
            {  name: "A",
               age: 20
            }
          ]
Run Code Online (Sandbox Code Playgroud)

问题在于列表中没有名称的元素inputB.订单没有原始订单inputA.对于原来的命令要坚持{ name: "A", age: 20 }应该来之前{ name: "C", age: 25 }

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

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

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

Fed*_*ner 3

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

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

您应该优化检查inputB,使其速度更快。为此,您可以创建一个HashSetfrom inputB.

这是代码:

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

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

只要您的年龄不等于 ,此方法就有效Integer.MAX_VALUE。

这个想法是,你总是按年龄进行比较,但如果一个元素不属于inputB,你就把年龄变成Integer.MAX_VALUE。这会产生两个效果:首先,它会让不包含在的元素inputB出现在底部;其次,当您总是 return 时Integer.MAX_VALUE,列表的顺序inputA会被保留,因为Collections.sort实现了稳定的排序。