PAYATHON 2026

Java 中如何根据另一个按位置配对的集合对 LinkedHashSet 元素排序?

数据阿明

可以按照两个 LinkedHashSet 的迭代顺序逐项配对,将配对结果按 pitch 升序排列,再取出对应的 slotID。示例数据的结果是 [3, 4, 5, 2, 1]。

确认去重后的配对关系

LinkedHashSet 按插入顺序迭代。重复添加已有元素不会增加新元素,也不会改变该元素的位置。原代码执行完毕后,两个集合的内容和迭代顺序如下:

slotIDs = [3, 1, 2, 5, 4]
pitches = [0.5, 2.2, 1.3, 1.1, 0.7]

按相同位置配对后,各元素的升序位置如下:

slotID配对的 pitch升序位置
30.5f1
12.2f5
21.3f4
51.1f3
40.7f2

将配对保存后再排序

下面的实现适用于 Java 8 及以上版本,假设集合和元素均非 null。它返回一个新的 List<Integer>,不会改变原来两个集合的顺序。

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

public final class SlotSorter {
    public static List<Integer> sortByPitch(
            LinkedHashSet<Integer> slotIDs,
            LinkedHashSet<Float> pitches) {

        if (slotIDs.size() != pitches.size()) {
            throw new IllegalArgumentException(
                    "slotIDs and pitches must have the same size");
        }

        List<Map.Entry<Integer, Float>> pairs =
                new ArrayList<>(slotIDs.size());

        Iterator<Integer> idIterator = slotIDs.iterator();
        Iterator<Float> pitchIterator = pitches.iterator();

        while (idIterator.hasNext()) {
            pairs.add(new AbstractMap.SimpleImmutableEntry<>(
                    idIterator.next(), pitchIterator.next()));
        }

        pairs.sort((a, b) ->
                Float.compare(a.getValue(), b.getValue()));

        List<Integer> result = new ArrayList<>(pairs.size());
        for (Map.Entry<Integer, Float> pair : pairs) {
            result.add(pair.getKey());
        }
        return result;
    }
}

在原问题的添加代码之后调用:

List<Integer> sortedSlotIDs = SlotSorter.sortByPitch(slotIDs, pitches);
System.out.println(sortedSlotIDs);
// [3, 4, 5, 2, 1]

比较 Float 值时使用 Float.compare。不要将两个值相减后强制转换为 int,这样会丢失小数差异,导致排序错误。该实现的时间复杂度为 O(n log n),额外空间复杂度为 O(n)。

如果结果仍需使用 LinkedHashSet

可以根据排序结果构造一个新的集合,它会按传入列表的顺序保存元素:

LinkedHashSet<Integer> sortedSlotIDs = new LinkedHashSet<>(
        SlotSorter.sortByPitch(slotIDs, pitches));

这个顺序来自排序后的列表,LinkedHashSet 本身不会根据 pitch 自动维护排序。

注意独立去重和位置配对的限制

两个集合长度相同是按位置配对的必要条件,但不能证明配对符合业务需求。两个集合会分别去重,如果其中一个集合比另一个少保留了一个元素,后续位置关系就可能发生偏移。使用这个方案的前提是:你确实要将两个集合最终保留的元素按位置配对。

配对完成后,建议将配对列表作为后续处理的数据来源。如果只重排 slotIDs,再将它与原顺序的 pitches 按位置配对,对应关系就会改变。

备注:内容仅供参考。