基于条件遍历不同长度已排序List,生成指定数量排序结果集
Hey there! Let's tackle this problem step by step.
First, let's clarify the core issue: you have two lists sorted by a date property in DESC order, and you want to create two result lists with a fixed number of records (e.g., count=3) while maintaining the sorted order. Your previous approach using a fixed-count for loop had safety risks—most likely because if one of the source lists is shorter than the target count, accessing elements via index would throw an IndexOutOfBoundsException.
The Safe Approach: Check Bounds & Iterate Smartly
Instead of a fixed-count for loop, we can use a loop that runs until we've filled the result list to the desired count or we've exhausted the source list. We'll add conditional checks to avoid accessing indices that don't exist.
Let's use a concrete example with Java (since you mentioned Lists, this is a common use case):
First, define a simple Record class to hold our data:
import java.time.LocalDate; public class Record { private LocalDate date; // Add other properties as needed public Record(LocalDate date) { this.date = date; } public LocalDate getDate() { return date; } }
Now, create a method that takes a sorted source list and target count, returning a safe, sorted result list:
import java.util.ArrayList; import java.util.List; public class ListProcessor { public static List<Record> createFixedSizeSortedList(List<Record> sortedSource, int targetCount) { List<Record> result = new ArrayList<>(); int currentIndex = 0; // Loop until we reach the target count OR run out of elements in the source list while (result.size() < targetCount && currentIndex < sortedSource.size()) { result.add(sortedSource.get(currentIndex)); currentIndex++; } return result; } }
Handling Both Lists & Conditional Selection
If your requirement is to select elements from both source lists to populate the two result lists (e.g., picking the top N records for each result based on date), here's how you can extend the logic with dual pointers:
Suppose we want to fill resultList1 and resultList2 each with up to count records, prioritizing the latest dates first across both lists:
public static void populateResultLists(List<Record> listA, List<Record> listB, List<Record> resultList1, List<Record> resultList2, int count) { int ptrA = 0; int ptrB = 0; // Fill resultList1 first while (resultList1.size() < count && (ptrA < listA.size() || ptrB < listB.size())) { Record nextA = ptrA < listA.size() ? listA.get(ptrA) : null; Record nextB = ptrB < listB.size() ? listB.get(ptrB) : null; // Conditional check to pick the latest date if (nextA != null && (nextB == null || nextA.getDate().isAfter(nextB.getDate()))) { resultList1.add(nextA); ptrA++; } else if (nextB != null) { resultList1.add(nextB); ptrB++; } } // Now fill resultList2 with remaining elements (still maintaining DESC order) while (resultList2.size() < count && (ptrA < listA.size() || ptrB < listB.size())) { Record nextA = ptrA < listA.size() ? listA.get(ptrA) : null; Record nextB = ptrB < listB.size() ? listB.get(ptrB) : null; if (nextA != null && (nextB == null || nextA.getDate().isAfter(nextB.getDate()))) { resultList2.add(nextA); ptrA++; } else if (nextB != null) { resultList2.add(nextB); ptrB++; } } }
Key Safety Improvements
- No Index Out-of-Bounds: We always check if the pointer is within the source list's bounds before accessing elements.
- Graceful Handling of Short Lists: If a source list runs out of elements, we just continue with the other list until we reach the target count.
- Maintains Sort Order: Since we're picking elements in DESC order (comparing dates each time), the result lists stay sorted as required.
Example Usage
public static void main(String[] args) { // Sample sorted lists (DESC order) List<Record> listA = List.of( new Record(LocalDate.of(2024, 5, 1)), new Record(LocalDate.of(2024, 4, 20)), new Record(LocalDate.of(2024, 4, 10)) ); List<Record> listB = List.of( new Record(LocalDate.of(2024, 4, 25)), new Record(LocalDate.of(2024, 4, 15)) ); int count = 3; List<Record> result1 = new ArrayList<>(); List<Record> result2 = new ArrayList<>(); populateResultLists(listA, listB, result1, result2, count); // Output result1 (should have 2024-05-01, 2024-04-25, 2024-04-20) System.out.println("Result List 1:"); result1.forEach(r -> System.out.println(r.getDate())); // Output result2 (should have 2024-04-15, 2024-04-10) System.out.println("\nResult List 2:"); result2.forEach(r -> System.out.println(r.getDate())); }
This approach eliminates the safety risks of your original fixed-count for loop while ensuring your result lists stay sorted and meet the fixed-size requirement.
内容的提问来源于stack exchange,提问作者Dasshield

