0

I am trying to sort an arraylist based on groupings. Suppose I have a list of currency and cash USD 100, CAD 75, USD 10, EUR 80, USD 5

I want to sort the list based on maximum cash for a currency descending order, so required out should look like. USD 100, USD 10, USD 5, EUR 80, CAD 75.

I wrote below classes to achieve the same but no luck, can somebody help.

import java.math.BigDecimal;
import java.util.Comparator;

public class BO {

    String ccy;
    BigDecimal cash;


public String getCcy() {
    return ccy;
}


public void setCcy(String ccy) {
    this.ccy = ccy;
}


public BigDecimal getCash() {
    return cash;
}


public void setCash(BigDecimal cash) {
    this.cash = cash;
}


@Override
public String toString() {
    return "BO [ccy=" + ccy + ", cash=" + cash + "]";
}
public static final Comparator<BO> CUSTOM_SORTER = new Comparator<BO>() {
    @Override
    public int compare(BO o1, BO o2) {
        return o2.getCash().compareTo(o1.getCash());
    }
};

}

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class BODriver {

public static void main(String[] args) {
BO one = new BO();
one.setCcy("USD");
one.setCash(new BigDecimal(100));
BO two = new BO();
two.setCcy("CAD");
two.setCash(new BigDecimal(50));
BO three = new BO();
three.setCcy("USD");
three.setCash(new BigDecimal(10));
BO four = new BO();
four.setCcy("EUR");
four.setCash(new BigDecimal(70));
BO five = new BO();
five.setCcy("USD");
five.setCash(new BigDecimal(5));

List<BO> boList = new ArrayList<BO>();
boList.add(five);
boList.add(four);
boList.add(three);
boList.add(two);
boList.add(one);

System.out.println("Before sort");
System.out.println(boList);
Collections.sort(boList,BO.CUSTOM);
System.out.println("After sort");
System.out.println(boList);

}

}
NItin
  • 33
  • 3
  • Possible duplicate of [How to compare objects by multiple fields](https://stackoverflow.com/questions/369512/how-to-compare-objects-by-multiple-fields) – tsolakp Feb 22 '18 at 17:51
  • No, first I have to identify maximum cash per currency and then sort the cash and currency using same order. – NItin Feb 22 '18 at 18:26
  • Can you add more examples so that it would be clear how you want to sort them? – tsolakp Feb 22 '18 at 19:34
  • Before sort: CAD 10, USD 20, USD 10, EUR 100, CAD 30, EUR 5 After sort: EUR 100, EUR 5, CAD 30, CAD 10, USD 20, USD 10 – NItin Feb 23 '18 at 13:10

3 Answers3

0

Maybe you can add a String field to BO class that concatenates ccy+" "+cash.e.g and you can use that string field to sort your objects easily.

Aeron Storm
  • 99
  • 1
  • 1
  • 11
  • First I have to identify maximum cash per currency and then sort the cash and currency using same order. – NItin Feb 22 '18 at 18:20
0
public static final Comparator<BO> CUSTOM_SORTER = new Comparator<BO>() {
    @Override
    public int compare(BO o1, BO o2) {
       if(o2.getCcy().compareTo(o1.getCcy())==0)
         return o2.getCash().compareTo(o1.getCash());
       else
         return o2.getCcy().compareTo(o1.getCcy());
    }
};

try this as your comparator..

Aeron Storm
  • 99
  • 1
  • 1
  • 11
0

Here is a two step process.

First find max for each currency:

    Map<String, BigDecimal> maxGroup = boList.stream().collect( 
    Collectors.toMap(BO::getCcy, BO::getCash, BigDecimal::max) );

Then sort first by max cash value, then by currency and finally by cash value in each BO object:

    Comparator<BO> comparator = Comparator
    .<BO, BigDecimal>comparing( (bo) -> maxGroup.get( bo.getCcy() ) ).reversed() //first compare by max cash in desc order
    .thenComparing(BO::getCcy) //then by currency
    .thenComparing( Comparator.comparing(BO::getCash).reversed() ); //and finally by cash in desc order

    Collections.sort( boList, comparator); 
tsolakp
  • 5,858
  • 1
  • 22
  • 28