Обьединение двух ArrayList по условию

Есть два листа

List<Report> ReportTrue, 
List<Report> ReportFalse, 

В одном элементы такие: 01 True (может быть несколько, 01 - это как будто месяц, true это их булевое поле), в другом 01 False (тоже может быть несколько или один)

Не могу додумать как их объединить в другой лист, чтобы был такой порядок

 01 True
 01 True
 01 False
 02 True
 02 False

и т.д

Сначала тру одного месяца потом фолс этого же месяца и т.д.

public List<Report> monthlyReportForUser(List<Report> ReportTrue, List<Report> ReportFalse) {

    List<Report> ReportListForUser = new ArrayList<>();
        
    int size = ReportTrue.size() + ReportFalse.size();
        
    for (int i = 0; i < size; i++) {
            
        if (ReportTrue.get(i).isExpense().ismouth() {
            ReportListForUser.add(ReportTrue.get(i));
        }
    }
        
    return monthlyReportListForUser;
}

Ответы (1 шт):

Автор решения: Alex Rudenko

Списки можно объединить просто используя конструктор / метод List::addAll и компаратор для сортировки сначала по месяцу, затем по значению true/false (так как false < true, для задания обратного порядка нужно использовать Comparator.reverseOrder):

List<Report> total = new ArrayList<>(reportTrue);
total.addAll(reportFalse);
total.sort(Comparator.comparing(Report::getMonth)
    .thenComparing(Report::isTrue, Comparator.reverseOrder()) // true before false
);
System.out.println(total);

или же используя Stream API Stream::concat + Stream::sorted и аналогичный компаратор:

List<Report> merged = Stream.concat(reportTrue.stream(), reportFalse.stream())
        .sorted(Comparator.comparingInt(Report::getMonth)
                .thenComparing(Report::isTrue, Comparator.reverseOrder()))
        .collect(Collectors.toList());
System.out.println(merged);

Есть ещё вариант с "алгоритмическим" слиянием через циклы, при обязательном условии, что оба списка уже отсортированы.

Здесь поочередно инкрементируются индексы в обоих списках:

List<Report> looped = new ArrayList<>();
int t = 0;
int f = 0;
int n = listTrue.size() + listFalse.size();
int k = 0;
while (k < n) {
    boolean trueFound = false;
    while (t < listTrue.size() && (f == listFalse.size() || listTrue.get(t).getMonth() <= listFalse.get(f).getMonth())) {
        looped.add(listTrue.get(t++));
        k++;
        trueFound = true;
    }
    if (trueFound) t--;

    while (f < listFalse.size() && (t == listTrue.size() || listFalse.get(f).getMonth() <= listTrue.get(t).getMonth())) {
        looped.add(listFalse.get(f++));
        k++;
    }
    if (trueFound) t++;
}
→ Ссылка