Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

316
Visualizações
Sort list by multiple fields and multiple criteria

I have the following code:

list.sort(Comparator
    .comparing(ProgrammData::getEnd)
    .thenComparing(ProgrammData::getStart).reversed());

My problem is that I want to have my list sorted by multiple things: 1.) Group them into future events and past events (By checking if the System.currentMilliseconds() is larger than the end timestamp) 2.) Sort future events by start ascending 3.) Sort past events by end descending

Can I do this with Java 8 Lambda or do I need another way of sorting the items?

Example:

events could look like this:
name, start, end
event1, 2022-02-220100, 2022-02-220300 
event2, 2022-02-220200, 2022-02-241800
event3, 2022-02-251200, 2022-02-281500
event4, 2022-02-261600, 2022-02-262100

if now() is 2022-02-221200 So the order should be:

event3 (next item in the future)
event4 (2nd next item in the future)
event2 (Ended closer to now than event1)
event1 (Longest in the past)
over 4 years ago · Santiago Trujillo
4 Respostas
Responde à pergunta

0

Try this :

    final long currentTime = System.currentTimeMillis();
    list.sort((el1, el2) -> {
        if (el1.equals(el2)) {
            return 0;
        }
        boolean isEl1Future = el1.getEnd().getTime() > currentTime;
        boolean isEl2Future = el2.getEnd().getTime() > currentTime;
        if (isEl1Future != isEl2Future) {
            return isEl1Future ? -1 : 1;
        }
        if (Boolean.TRUE.equals(isEl1Future)) {
            return el1.getStart().before(el2.getStart()) ? -1 : 1;
        }
        return el1.getEnd().after(el2.getEnd()) ? -1 : 1;
    });
over 4 years ago · Santiago Trujillo Relatório

0

There are multiple things to notice. First, one is the .thenComparing(...) method, which is only taking place if the previous comparing results are equal. You can read more about its behavior in the docs.

Second, if I were you I wouldn't bother to overuse the stream if I could solve it with one simple comparator. Assuming that you are looking for a new instance of the ProgrammData list, I wrote my code in stream style, but the Comparator can be used with the List's sort method.

private List<ProgrammData> sortedProgramms(List<ProgrammData> dataList) {
    final LocalDateTime now = LocalDateTime.now();
    return dataList.stream()
                    .sorted((e1, e2) -> {
                        if (e1.getStart().isAfter(now) && e2.getStart().isAfter(now)) {
                            return e1.getStart().compareTo(e2.getStart());
                        }
                        return e2.getEnd().compareTo(e1.getEnd());
                    })
                    .collect(Collectors.toList());
 }

The LocalDateTime().now() is using System.currentTimeMillis() inside, if there is not a more accurate given clock.

over 4 years ago · Santiago Trujillo Relatório

0

You need to split past and future events in different lists and sort them accordingly. The final step is to join both lists.

  public static void main(String[] args) {
    ProgrammData programmData1 = new ProgrammData("a", LocalDateTime.now().plusDays(1),
        LocalDateTime.now().plusDays(1));
    ProgrammData programmData2 = new ProgrammData("b", LocalDateTime.now().plusDays(2),
        LocalDateTime.now().plusDays(2));
    ProgrammData programmData3 = new ProgrammData("c", LocalDateTime.now().minusDays(1),
        LocalDateTime.now().minusDays(1));
    ProgrammData programmData4 = new ProgrammData("c", LocalDateTime.now().minusDays(2),
        LocalDateTime.now().minusDays(2));

    List<ProgrammData> programmDataList = new ArrayList<>();

    programmDataList.add(programmData1);
    programmDataList.add(programmData2);
    programmDataList.add(programmData3);
    programmDataList.add(programmData4);

    final List<ProgrammData> collect = programmDataList.stream().sorted(Comparator
        .comparing(ProgrammData::end)).toList();

    LocalDateTime localDateTime = LocalDateTime.now();
    final List<ProgrammData> pastEvents = collect.stream().filter(pd -> pd.end.isBefore(localDateTime))
        .sorted(Comparator
            .comparing(ProgrammData::end).reversed()).toList();
    final List<ProgrammData> futureEvents = collect.stream().filter(pd -> pd.end.isAfter(localDateTime)).toList();

    List<ProgrammData> sortedListAsRequired = new ArrayList<>();

    sortedListAsRequired.addAll(futureEvents);
    sortedListAsRequired.addAll(pastEvents);

    System.out.println(sortedListAsRequired);
  }

  static record ProgrammData(String name, LocalDateTime start, LocalDateTime end) {

  }

The result is something like this:

[ProgrammData[name=a, start=2022-02-23T18:08:59.564300200, end=2022-02-23T18:08:59.568806900], ProgrammData[name=b, start=2022-02-24T18:08:59.568806900, end=2022-02-24T18:08:59.568806900], ProgrammData[name=c, start=2022-02-21T18:08:59.568806900, end=2022-02-21T18:08:59.568806900], ProgrammData[name=c, start=2022-02-20T18:08:59.568806900, end=2022-02-20T18:08:59.568806900]]
over 4 years ago · Santiago Trujillo Relatório

0

Your example is confusing. As you state in the heading event2 should be handled as if it's in the future, due it's end time (2022-02-241800) is after now (2022-02-221200), so the ordered elements shoud be

event2
event3
event4
event1

If that's correct, you could try something like the following:

events.sort((e1, e2) -> {
    // -1: e1 and e2 in the past
    //  0: e1 and e2 in distinct periods
    // +1: e1 and e2 in the future
    int period = Integer.signum(
          Integer.signum(e1.getEnd().compareTo(now))
        + Integer.signum(e2.getEnd().compareTo(now))
    );
    if (period == 0) {
        return -e1.getEnd().compareTo(now);
    }
    // > 0: e1 is after e2
    // = 0: e1 is equal to e2
    // < 0: e1 is before e2
    int comparation = e1.getComparingDateTime(now).compareTo(
        e2.getComparingDateTime(now)
    );
    return period * comparation;
});

Given

class ProgramData {
    ...
    public LocalDateTime getComparingDateTime(LocalDateTime reference) {
        if (reference.isAfter(end)) {
            // Past
            return end;
        }
        // Future
        return start;
    }
    ...
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda