2

I have an ArrayList in Java and each element in the list is an object with 3 fields (a, b and c). I should order by a in ascending order; if 2 elements have the same value for a, they should be ordered by b in descending order; finally, if 2 elements have the same value even for b, they should be ordered by c in ascending order.

I tried other solutions posted on stackoverflow that are based on Comparator, but I did not get to order in descending order.

Could anyone kindly help me? Many thanks!

pinux10
  • 31
  • 4

2 Answers2

7

Comparator.reversed() for descending order

    Comparator<Element> compar = Comparator.comparing(Element::getA)
            .thenComparing(Comparator.comparing(Element::getB).reversed())
            .thenComparing(Element::getC);
    yourArrayList.sort(compar);

In addition to the reversed method I am exploiting the fact that thenComparing() is overloaded: one thenComparing() takes a Comparator as argument, which we need for reversing, the other just takes a method reference (or lambda) as argument (a Function in the declaration of thenComparing()).

If either a, b or c is a primitive int, long or double remember to use comparingInt(), comparingLong(), comparingDouble(), thenComparingInt(), etc.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

Your Comparator for b needs to return a negative value if comparing o1 to o2 (where o1 is the first argument and o2 is the second), and o1.b is greater than o2.b. A Comparator returns negative when the first argument is comparably smaller (before) the second. As you want elements with greater b values to be interpreted as comparably smaller, reverse the return types from a typical ascending order Integer compare.

  class Obj {
    int a;
    int b;
    int c;

    Obj(int a, int b, int c) {
      this.a = a;
      this.b = b;
      this.c = c;
    }

    @Override
    public String toString() {
      return "{a: " + a + ", b: " + b + ", c: " + c + "}";
    }
  }

  public void sortObjs() {
    ArrayList<Obj> list = new ArrayList<>();

    list.add(new Obj(0, 1, 2));
    list.add(new Obj(0, 2, 2));
    list.add(new Obj(1, 1, 2));
    list.add(new Obj(1, 1, 1));

    list.sort((o1, o2) -> {
      if (o1.a != o2.a) {
        return o1.a - o2.a;
      }
      //if Objects' a fields are equal but b is not, sort by b in descending order
      if (o1.b != o2.b) {
        return o2.b - o1.b;
      }
      return o1.c - o2.c;
    });

    System.out.println(list);

  }

  public static void main(String[] args) {
    new Main().sortObjs();
  }
}

Output:

[{a: 0, b: 2, c: 2}, {a: 0, b: 1, c: 2}, {a: 1, b: 1, c: 1}, {a: 1, b: 1, c: 2}]
Patrick
  • 39
  • 1
  • 6