You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Comparator自定义排序:保留特定值对象的原始位置

自定义Comparator排序问题:保留-1值元素原始位置,其余降序排列

需求描述

对Candidate对象列表排序,规则为:

  • 值为-1的对象保留原始位置
  • 其余对象按值降序排列

输入示例

Candidate candidate1 = new Candidate("id1",  0.4);
Candidate candidate2 = new Candidate("id2", -1.0);
Candidate candidate3 = new Candidate("id3", 0.8);
List<Candidate> inputCandidates = ImmutableList.of(candidate1, candidate2, candidate3);

期望输出

[
    Candidate(super=Candidate(id=id3), value=0.8), 
    Candidate(super=Candidate(id=id2), value=-1.0), 
    Candidate(super=Candidate(id=id1), value=0.4)
]

当前实现代码

public final Comparator<Candidate> customComparator() {
    return (Candidate one, Candidate two) -> {
        double scoreOne =  one.getValue() != null ? one.getValue() : 0d;
        double scoreTwo =  two.getValue() != null ? two.getValue() : 0d;
        if (scoreOne == scoreTwo) return 0;
        if (scoreOne == -1.0d) return 1;
        if (scoreTwo == -1.0d) return -1;
        return Double.compare(scoreTwo, scoreOne);
    };
}

实际输出

[
    Candidate(super=Candidate(id=id3), value=0.8), 
    Candidate(super=Candidate(id=id1), value=0.4), 
    Candidate(super=Candidate(id=id2), value=-1.0)
]

错误原因

你的Comparator逻辑无法实现需求——标准Comparator仅通过元素两两比较确定相对顺序,无法记录元素的原始索引,自然没法保留特定元素的原始位置。

当前代码中,只要遇到值为-1的元素,会强制将其往后排(和非-1元素比较时,-1元素会被判定为"更大",所以排序后移到末尾),这完全违背了"保留原始位置"的要求。


解决方案

要实现需求,必须结合元素的原始索引来排序,步骤如下:

  1. 将每个Candidate与它的原始索引绑定(用现成的AbstractMap.SimpleEntry或自定义类);
  2. 对绑定后的列表排序:
    • 若两个元素都是-1值,按原始索引升序保留相对位置;
    • 若其中一个是-1值,按原始索引升序排列,确保-1元素留在原位置;
    • 若都不是-1值,按score降序排列;
  3. 提取排序后的Candidate对象,得到最终列表。

示例代码

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class CandidateSorter {
    public static List<Candidate> sortWithMinus1Retained(List<Candidate> input) {
        // 绑定元素与原始索引
        List<Map.Entry<Candidate, Integer>> indexedCandidates = IntStream.range(0, input.size())
                .mapToObj(index -> new AbstractMap.SimpleEntry<>(input.get(index), index))
                .collect(Collectors.toList());

        // 自定义排序逻辑
        indexedCandidates.sort((entry1, entry2) -> {
            Candidate c1 = entry1.getKey();
            Candidate c2 = entry2.getKey();
            double score1 = c1.getValue() != null ? c1.getValue() : 0d;
            double score2 = c2.getValue() != null ? c2.getValue() : 0d;

            boolean isC1Minus1 = score1 == -1.0d;
            boolean isC2Minus1 = score2 == -1.0d;

            if (isC1Minus1 && isC2Minus1) {
                // 两个都是-1,按原始索引升序保留相对位置
                return Integer.compare(entry1.getValue(), entry2.getValue());
            } else if (isC1Minus1 || isC2Minus1) {
                // 其中一个是-1,按原始索引升序,确保原位置不变
                return Integer.compare(entry1.getValue(), entry2.getValue());
            } else {
                // 都不是-1,按score降序排列
                return Double.compare(score2, score1);
            }
        });

        // 提取排序后的Candidate对象
        return indexedCandidates.stream()
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }
}

调用该方法后,输入示例列表将得到你期望的输出结果。


内容的提问来源于stack exchange,提问作者Prathamesh Mahankal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 21:24:57