Сортировка Java по разбросу между двумя BigDecimal

Помогите, пожалуйста, с сортировкой в ​​Java. У меня есть простой пример (выглядит так). Мне нужно отсортировать список по разнице между двумя BigDecimals.

Мой класс данных (я вырезал геттеры)

    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;
    }
    }

Здесь мы храним наши записи.

        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

И мне просто нужно отсортировать этот список по разнице между bidPrice и askPrice. Я попробовал этот метод...

    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;
    }
    }

Но безуспешно...

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

Список смешанный, но не отсортированный по моим критериям! Разворот не отсортирован!

Как правильно отсортировать этот список по разбросу?

У меня нет большого опыта в java. И все мои попытки ни к чему не привели.

Я бы добавил метод getSpread() (или calcSoread()) к Quotation и отсортировал по нему. (вроде sort(sortedBySpread, Comparator.comparingInt(Quotation::getSpread))

user16320675 30.01.2023 13:34

Эээ, что происходит, когда дельта между этими двумя полями не является допустимым целым числом? Какой смысл использовать BigDecimal, когда вы полагаетесь на такой подверженный ошибкам способ их вычитания? (Например, у BigDecimal есть метод subtract... если вас беспокоят накладные расходы, почему бы не вычислить это значение при построении объектов цитаты)?

GhostCat 30.01.2023 13:49

Кстати, сократите код как запись: public record Quotation ( long id , BigDecimal askPrice , BigDecimal bidPrice ) {}

Basil Bourque 30.01.2023 21:08
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
3
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Collections.sort(sortedBySpread, (a, b) -> (a.getBidPrice().intValue() - b.getAskPrice().intValue())); выполняет некоторую математику, которая мало что дает, поскольку она вычитает аск из ставки двух разных котировок.

Вместо этого вы должны рассчитать распространение a, а затем вычесть распространение b:

Collections.sort(sortedBySpread, (a, b) -> (a.getBidPrice().intValue() - a.getAskPrice().intValue()) - (b.getBidPrice().intValue() - b.getAskPrice().intValue()));

Как правило, это можно расширить до следующего, чтобы было более понятно, что происходит:

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;
});

Но, начиная с первого фрагмента, IntelliJ предлагает более чистое решение.

Collections.sort(sortedBySpread, Comparator.comparingInt(a -> (a.getBidPrice().intValue() - a.getAskPrice().intValue())));

И, исходя из этого, может иметь смысл поставить getSpread на Quotation:

public int getSpread() {
    return bidPrice.intValue() - askPrice.intValue();
}

что тогда позволит

Collections.sort(sortedBySpread, Comparator.comparingInt(Quotation::getSpread));

И наконец

sortedBySpread.sort(Comparator.comparingInt(Quotation::getSpread));

без необходимости Collections.sort.

Большое спасибо ! Ваш ответ решил проблему! Я только сейчас понял концепцию a и b.

Anatolii 30.01.2023 13:31

Для демонстрации я помещаю ваши значения в список. Я также добавил следующее в ваш класс.

public BigDecimal getSpread() {
       return askPrice.subtract(bidPrice);
}
public String toString() {
       return "id - %d    bid - %6.2f     ask - %6.2f     spread - %6.2f".formatted(id, bidPrice, askPrice,getSpread());   
}

Данные

 List<Quotation> quotes = new ArrayList<>(List.of(
   (new Quotation(1000,new BigDecimal("99"), new BigDecimal("104"))),
   (new Quotation(1001,new BigDecimal("69"), new BigDecimal("72"))),
   (new Quotation(1002,new BigDecimal("65"), new BigDecimal("69"))),
   (new Quotation(1003,new BigDecimal("70"), new BigDecimal("71"))),
   (new Quotation(1004,new BigDecimal("71"), new BigDecimal("73"))),
   (new Quotation(1005,new BigDecimal("90"), new BigDecimal("95"))),
   (new Quotation(1006,new BigDecimal("92"), new BigDecimal("93"))),
   (new Quotation(1007,new BigDecimal("94"), new BigDecimal("98"))),
   (new Quotation(1008,new BigDecimal("90"), new BigDecimal("92"))),
   (new Quotation(1009,new BigDecimal("92"), new BigDecimal("95")))));

Сортировочная часть проста. Просто используйте компаратор, ссылаясь на спред.

quotes.sort(Comparator.comparing(Quotation::getSpread));

И распечатать

for(Quotation q : quotes) {
    System.out.println(q);
} 

Отпечатки

id - 1003    bid -  70.00     ask -  71.00     spread -   1.00
id - 1006    bid -  92.00     ask -  93.00     spread -   1.00
id - 1004    bid -  71.00     ask -  73.00     spread -   2.00
id - 1008    bid -  90.00     ask -  92.00     spread -   2.00
id - 1001    bid -  69.00     ask -  72.00     spread -   3.00
id - 1009    bid -  92.00     ask -  95.00     spread -   3.00
id - 1002    bid -  65.00     ask -  69.00     spread -   4.00
id - 1007    bid -  94.00     ask -  98.00     spread -   4.00
id - 1000    bid -  99.00     ask - 104.00     spread -   5.00
id - 1005    bid -  90.00     ask -  95.00     spread -   5.00

      

Кстати, если вы хотите изменить порядок сортировки на обратный, вы можете добавить reversed() в конец comparator. Например. quotes.sort(Comparator.comparing(Quotation::getSpread).rever‌​sed());

WJS 30.01.2023 14:05

Другие вопросы по теме