Please help with sorting in Java. I have a simple example (looks like this). I need to sort list by the difference between two BigDecimals.
My Data class (I cut getters)
public class Quotation {
private final long id;
private final BigDecimal askPrice;
private final BigDecimal bidPrice;
public Quotation(long id, BigDecimal bidPrice, BigDecimal askPrice) {
this.id = id;
this.askPrice = askPrice;
this.bidPrice = bidPrice;
}
}
Here we store our records.
storeQuotation(new Quotation(1000,new BigDecimal("99"), new BigDecimal("104")));
storeQuotation(new Quotation(1001,new BigDecimal("69"), new BigDecimal("72")));
storeQuotation(new Quotation(1002,new BigDecimal("65"), new BigDecimal("69")));
storeQuotation(new Quotation(1003,new BigDecimal("70"), new BigDecimal("71")));
storeQuotation(new Quotation(1004,new BigDecimal("71"), new BigDecimal("73")));
storeQuotation(new Quotation(1005,new BigDecimal("90"), new BigDecimal("95")));
storeQuotation(new Quotation(1006,new BigDecimal("92"), new BigDecimal("93")));
storeQuotation(new Quotation(1007,new BigDecimal("94"), new BigDecimal("98")));
storeQuotation(new Quotation(1008,new BigDecimal("90"), new BigDecimal("92")));
storeQuotation(new Quotation(1009,new BigDecimal("92"), new BigDecimal("95")));
out - Not Sorted
id - 1000. Bid - 99. Ask - 104. Spread = 5
id - 1001. Bid - 69. Ask - 72. Spread = 3
id - 1002. Bid - 65. Ask - 69. Spread = 4
id - 1003. Bid - 70. Ask - 71. Spread = 1
id - 1004. Bid - 71. Ask - 73. Spread = 2
id - 1005. Bid - 90. Ask - 95. Spread = 5
id - 1006. Bid - 92. Ask - 93. Spread = 1
id - 1007. Bid - 94. Ask - 98. Spread = 4
id - 1008. Bid - 90. Ask - 92. Spread = 2
id - 1009. Bid - 92. Ask - 95. Spread = 3
And I just need to sort this list by the difference between bidPrice and askPrice. I tried this method...
public static List<Quotation> getSpreadsList(boolean decreasing) {
List<Quotation> sortedBySpread = QuotationsStoreImpl.quotationList;
Collections.sort(sortedBySpread, (a, b) ->
(a.getBidPrice().intValue() - b.getAskPrice().intValue()));
// sortedBySpread.sort((a, b) ->
// (a.getBidPrice().intValue() - b.getAskPrice().intValue()));
if (decreasing) {
Collections.reverse(sortedBySpread);
}
return sortedBySpread;
}
}
But without success...
out - Sorted
id - 1002. Bid - 65. Ask - 69. Spread = 4
id - 1003. Bid - 70. Ask - 71. Spread = 1
id - 1004. Bid - 71. Ask - 73. Spread = 2
id - 1001. Bid - 69. Ask - 72. Spread = 3
id - 1008. Bid - 90. Ask - 92. Spread = 2
id - 1009. Bid - 92. Ask - 95. Spread = 3
id - 1006. Bid - 92. Ask - 93. Spread = 1
id - 1007. Bid - 94. Ask - 98. Spread = 4
id - 1005. Bid - 90. Ask - 95. Spread = 5
id - 1000. Bid - 99. Ask - 104. Spread = 5
The list is mixed but not sorted according to my criteria ! Spread not sorted !
How can I sort this list correct, by spread ?
I don't have much experience in java. And all my attempts have come to nothing.
Collections.sort(sortedBySpread, (a, b) -> (a.getBidPrice().intValue() - b.getAskPrice().intValue()));
does some math that makes little since since it subtracts the ask from the bid of two different quotes.
Instead you should calculate the spread of a
and then subtract the spread of b
:
Collections.sort(sortedBySpread, (a, b) -> (a.getBidPrice().intValue() - a.getAskPrice().intValue()) - (b.getBidPrice().intValue() - b.getAskPrice().intValue()));
Generally this could be expanded into the following to make it more clear what is going on:
Collections.sort(sortedBySpread, (Quotation a, Quotation b) -> {
int spreadA = a.getBidPrice().intValue() - a.getAskPrice().intValue();
int spreadB = b.getBidPrice().intValue() - b.getAskPrice().intValue();
return spreadA - spreadB;
});
But starting with the first snippet IntelliJ suggest the arguably far cleaner solution
Collections.sort(sortedBySpread, Comparator.comparingInt(a -> (a.getBidPrice().intValue() - a.getAskPrice().intValue())));
And going from there it might make sense to have a getSpread
on Quotation
:
public int getSpread() {
return bidPrice.intValue() - askPrice.intValue();
}
which would then allow
Collections.sort(sortedBySpread, Comparator.comparingInt(Quotation::getSpread));
And finally
sortedBySpread.sort(Comparator.comparingInt(Quotation::getSpread));
without the need for Collections.sort
.