Java 按可为空字段排序,表示项目';s位置
我需要以自定义方式对对象数组进行排序。 假设我的对象中有两个字段-Java 按可为空字段排序,表示项目';s位置,java,spring,java-stream,comparator,comparable,Java,Spring,Java Stream,Comparator,Comparable,我需要以自定义方式对对象数组进行排序。 假设我的对象中有两个字段-priority(可空)和createdAt(不可空)。 优先级字段表示项目应位于哪个位置。但是,它可以为null。在这种情况下,我们应该考虑createdAt字段(降序)进行排序 让我举例说明。 例如,我的对象是: Object0: priority: null, createdAt: 2018-12-01 Object1: priority: 1, createdAt: 2018-12-02 Object2: prior
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;
}
不,不要使用比较器进行此操作,或者更准确地说,不要对整个作业使用比较器。比较器的工作是比较两个对象并告诉它们之间的顺序。它不适合检测优先级序列中的间隙 相反,假设优先级是整数且唯一的,我建议您对具有已定义优先级的对象使用数组和基数排序。优先级1进入数组索引1、优先级2索引2等。优先级为
null
的对象在创建日期降序时使用比较器进行排序,然后填充到仍然为null
的数组索引中(我想索引0除外)
“假设优先级是完整的和唯一的”,我的意思是,你不会冒两个优先级为3的对象或优先级为2.44的对象的风险
我可以使用流和收集器.partitioning by
来分离具有优先级的对象和没有优先级的对象,当然还有其他方法
我会手工编码的。我从来没有听说过任何现成的解决办法。搜索永远不会有什么害处,但我会惊讶地发现一个。另一方面,不需要太多的代码行
顺便说一句,对日期使用
LocalDate
,因为它们没有时间(而不是LocalDateTime
)。给定所有对象的列表:数组可以根据优先级设置位置:
List<MyObject> list = new ArrayList<>(Arrays.asList(...));
MyObject[] res = new MyObject[list.size()];
int indicList = 0;
for (int i = 0; i < res.length; i++) {
if (res[i] == null) {
res[i] = list.get(indicList++);
}
}
int indicilist=0;
for(int i=0;i
- 一种可能的方法(对效率不是很确定)是:
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)));
List customObjectList=new ArrayList();//你的初始化;
//仅按createdAt降序排序优先级为空的对象的列表
List nullValues=customObjectList.stream()
.filter(a->a.getPriority()==null)
.sorted(Comparator.comparing(CustomObject::getCreatedAt).reversed())
.collect(Collectors.toList());
//按优先级升序排序的剩余非空优先级对象
List remainingValues=customObjectList.stream()
.filter(a->a.getPriority()!=null)
.sorted(Comparator.comparing(CustomObject::getPriority))
.collect(Collectors.toList());
//与初始列表大小相同的最终列表
List finalList=newarraylist(customObjectList.size());
//首先设置基于优先级的索引
remainingValues.forEach(a->finalList.add(a.getPriority(),a));
//遍历最终列表并填充空槽
//在弹出(`remove(0)`)按createdAt降序排序的列表中的元素时
IntStream.range(0,finalList.size())
.filter(i->finalList.get(i)==null)
.forEach(i->finalList.add(i,nullValues.remove(0));
注意:这里很少有假设
-列表中设置了基于0
的优先级。
-非空优先级值是
finalList
中的精确索引。您能给出与之相关的类吗?老实说,我没有该类。我的情况更复杂,在这里我把它减少到最低限度。我将编辑我的文章,但是提供最小类。为什么object6和object4介于object5和object2之间?您可以轻松地使用自己的比较器lambda进行排序,但我不清楚您的算法。Object5的优先级为2,因此它将进入位置2。Object2的优先级为5,因此它将转到位置5。当所有对象都位于它们的位置时,我们使用按createdAt排序的对象填充数组中的左空格。我希望它现在会更清楚。你不能这样排序,因为你说你需要优先权作为索引,而这不是它的工作方式,你只能比较它们之间的元素,before/after/equalsOk。所以我知道没有比较标准。有道理:)你知道有什么现成的解决办法吗?是的,这就是我的意思。:-)您可能需要考虑到最大优先级可能大于对象数,我不知道,询问者应该知道。正如我所想的那样,finalList.set(a.getPriority(),a)
抛出一个java.lang.IndexOutOfBoundsException:Index:1,Size:0
,通过添加更改设置
是否会更改problem@azro好的,没有测试这个,更新为使用add
.f***我的头脑总是忘记“不”。。。大脑太快,手拿不动,“改加不改问题”不知道如何解决it@azro好的,让我用一个更好的测试代码回到这里,如果是这样的话,通常需要对列表进行初始化。
int indicList = 0;
for (int i = 0; i < res.length; i++) {
if (res[i] == null) {
res[i] = list.get(indicList++);
}
}
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)));