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

Java中基于Comparator按特定规则实现对象列表排序的技术求助

解决Java对象列表的自定义排序需求

Hey there! Let's break down how to implement your custom sorting rules step by step. First, let's recap your requirements to make sure we cover everything:

  • Group pairs of objects where one's partId matches the other's id
  • Move all objects with partId == null to the end of the list
  • Sort the groups by count with two priorities:
    1. First prioritize groups where both count values are smaller
    2. Then prioritize groups where at least one count is smaller than other groups

Step 1: Define the Entity Class

First, let's assume your object is an Item class with the required fields (adjust if your actual class differs):

class Item {
    private Long id;
    private Long partId;
    private Integer count;

    // Constructor, getters, toString
    public Item(Long id, Long partId, Integer count) {
        this.id = id;
        this.partId = partId;
        this.count = count;
    }

    public Long getId() { return id; }
    public Long getPartId() { return partId; }
    public Integer getCount() { return count; }

    @Override
    public String toString() {
        return "Item{id=" + id + ", partId=" + partId + ", count=" + count + "}";
    }
}

Step 2: Implement the Sorting Logic

Instead of trying to handle everything in a single Comparator (which would get messy), we'll split the process into manageable steps:

  1. Separate Null and Non-Null partId Items: First, we split the list to easily move null partId items to the end later.
  2. Group Pairing Items: We find pairs where one's partId matches the other's id, marking processed items to avoid duplicates.
  3. Sort the Groups: We sort groups using your priority rules: compare the smallest count first, then the largest count in each group.
  4. Sort Within Groups: Each group's elements are sorted by count in ascending order.
  5. Merge Lists: Combine the sorted non-null groups with the null partId items (added to the end).

Here's the full implementation:

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

public class ListTTest {
    public static void main(String[] args) {
        // Test data - adjust to match your actual objects
        List<Item> items = Arrays.asList(
                new Item(1L, 2L, 3),
                new Item(2L, 1L, 2),
                new Item(3L, 4L, 1),
                new Item(4L, 3L, 4),
                new Item(5L, null, 5),
                new Item(6L, 7L, 2),
                new Item(7L, 6L, 1),
                new Item(8L, null, 0)
        );

        // 1. Split items into non-null partId and null partId lists
        Map<Boolean, List<Item>> splitItems = items.stream()
                .collect(Collectors.partitioningBy(item -> item.getPartId() == null));
        List<Item> nonNullPartIdItems = splitItems.get(false);
        List<Item> nullPartIdItems = splitItems.get(true);

        // 2. Group paired items (partId matches another item's id)
        Set<Long> processedIds = new HashSet<>();
        List<List<Item>> groups = new ArrayList<>();

        for (Item item : nonNullPartIdItems) {
            if (processedIds.contains(item.getId())) continue;

            // Find the matching pair
            Optional<Item> pairOpt = nonNullPartIdItems.stream()
                    .filter(pair -> !processedIds.contains(pair.getId())
                            && (Objects.equals(item.getPartId(), pair.getId())
                            || Objects.equals(pair.getPartId(), item.getId())))
                    .findFirst();

            if (pairOpt.isPresent()) {
                Item pair = pairOpt.get();
                groups.add(Arrays.asList(item, pair));
                processedIds.add(item.getId());
                processedIds.add(pair.getId());
            } else {
                // Handle unpaired items (if any) by adding them as single-item groups
                groups.add(Collections.singletonList(item));
                processedIds.add(item.getId());
            }
        }

        // 3. Sort groups by your priority rules
        groups.sort((group1, group2) -> {
            // Get sorted count lists for easy comparison
            List<Integer> counts1 = group1.stream().map(Item::getCount).sorted().toList();
            List<Integer> counts2 = group2.stream().map(Item::getCount).sorted().toList();

            // Priority 1: Compare smallest count first
            int minCountCompare = counts1.get(0).compareTo(counts2.get(0));
            if (minCountCompare != 0) {
                return minCountCompare;
            }

            // Priority 2: Compare largest count if smallest counts are equal
            int maxCount1 = counts1.size() > 1 ? counts1.get(1) : counts1.get(0);
            int maxCount2 = counts2.size() > 1 ? counts2.get(1) : counts2.get(0);
            return Integer.compare(maxCount1, maxCount2);
        });

        // 4. Sort elements within each group and flatten the groups
        List<Item> sortedNonNullItems = groups.stream()
                .flatMap(group -> {
                    group.sort(Comparator.comparingInt(Item::getCount));
                    return group.stream();
                })
                .collect(Collectors.toList());

        // 5. Merge sorted non-null items with null partId items (at the end)
        List<Item> finalSortedList = new ArrayList<>(sortedNonNullItems);
        finalSortedList.addAll(nullPartIdItems);

        // Print the result
        System.out.println("Final Sorted List:");
        finalSortedList.forEach(System.out::println);
    }
}

Key Explanations

  • Grouping: We use a HashSet to track processed IDs so we don't create duplicate groups.
  • Group Sorting: By sorting each group's count values, we can easily compare the smallest and largest values to meet your priority rules. For example, a group with counts [1,2] will come before [1,3] (since the largest count is smaller), and [1,4] comes before [2,3] (since the smallest count is smaller).
  • Null Handling: Separating null partId items first makes it trivial to append them to the end of the sorted list.

When you run this code, the output will match your requirements: paired groups sorted by the count priorities, with all null partId items at the end.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:24:44