我需要以自定义方式对对象数组进行排序。
假设我的对象中有两个字段-priority
(可为空)和createdAt
(不可为空)。
优先级字段表明该项目应位于哪个位置。但是,它可以为null。在这种情况下,我们应考虑createdAt字段(以降序排列)进行排序。
让我用示例进行解释。 例如,我的对象将是:
Object0: priority: null, createdAt: 2018-12-01
Object1: priority: 1, createdAt: 2018-12-02
Object2: priority: 5, createdAt: 2018-12-03
Object3: priority: null, createdAt: 2018-12-04
Object4: priority: null, createdAt: 2018-12-05
Object5: priority: 2, createdAt: 2018-12-06
Object6: priority: null, createdAt: 2018-12-07
最终订单应为:
我如何实现我的目标?是否有任何现成的比较器就绪?
编辑: 我认为我们可以使用该类:
public class MyObject {
Integer priority;
LocalDateTime createdAt;
}
答案 0 :(得分:2)
否,请勿为此使用比较器,或者更确切地说,不要针对整个工作使用比较器。比较器的工作是比较两个对象,并确定两个对象之间的顺序。它不适用于检测优先级序列中的缺口。
相反,假设优先级是不可分割的且唯一的,我建议您对定义了优先级的对象使用数组和一种基数排序。优先级1进入数组索引1,优先级2索引2,依此类推。优先级为null
的对象在创建日期降序时用比较器进行排序,然后填充到仍为null
的数组索引中(除了索引0,我想)。
“假设优先级是不可分割的且唯一的”,我的意思是您不会冒两个优先级为3的对象或优先级为2.44的对象的风险。
我可能使用流和Collectors.partitioningBy
来将具有优先级的对象与没有优先级的对象分开,但是当然还有其他方法。
我要为此手动编码。我从未听说过任何现成的解决方案。搜索永远不会有害,但是我很惊讶地发现了一个。另一方面,不需要那么多代码行。
顺便说一句,LocalDate
用于您的日期,因为他们没有时间(不是LocalDateTime
)。
答案 1 :(得分:2)
给出所有对象的列表:一个数组可以根据优先级设置位置:
List<MyObject> list = new ArrayList<>(Arrays.asList(...));
MyObject[] res = new MyObject[list.size()];
遍历您必须放置的具有优先级的对象
for (Iterator<MyObject> ite = list.iterator(); ite.hasNext(); ) {
MyObject obj = ite.next();
if (obj.getPriority() != null) {
res[obj.getPriority() - 1] = obj;
ite.remove();
}
}
通过降序createdAt
list.sort(Comparator.comparing(MyObject::getCreatedAt).reversed());
将它们插入数组的空框中
int indicList = 0;
for (int i = 0; i < res.length; i++) {
if (res[i] == null) {
res[i] = list.get(indicList++);
}
}
答案 2 :(得分:1)
涉及流的一种可能的方法(不太确定效率)可能是:
List<CustomObject> customObjectList = new ArrayList<>(); // your initialisation;
// list of only those objects whose priority is null sorted descending by createdAt
List<CustomObject> nullValues = customObjectList.stream()
.filter(a -> a.getPriority() == null)
.sorted(Comparator.comparing(CustomObject::getCreatedAt).reversed())
.collect(Collectors.toList());
// remaining non null priority objects sorted by priority ascending
List<CustomObject> remainingValues = customObjectList.stream()
.filter(a -> a.getPriority() != null)
.sorted(Comparator.comparing(CustomObject::getPriority))
.collect(Collectors.toList());
// final list of same size as initial
List<CustomObject> finalList = new ArrayList<>(customObjectList.size());
// set the priority based indexes first
remainingValues.forEach(a -> finalList.add(a.getPriority(), a));
// iterate through the final list and fill in the empty slots
// while popping(`remove(0)`) the element from list sorted descending by createdAt
IntStream.range(0, finalList.size())
.filter(i -> finalList.get(i) == null)
.forEach(i -> finalList.add(i, nullValues.remove(0)));
注意 :此处很少有假设
-列表中设置了基于0
的优先级。
-非空优先级值是finalList