Как объединить фильтры в потоках для упрощения

У меня есть следующий метод, который принимает список CustomClass и выполняет фильтры с использованием потоков и возвращает результат на каждом этапе на основе результата фильтра.

Мне было интересно, есть ли способ упростить код, объединив фильтры и операторы вместе, чтобы сделать его более кратким и эффективным.

public String transform(List<CustomObject> listOfObjects) {

       listOfObjects = listOfObjects.stream()
            .filter(object -> object.objectType().equals("BUSINESS")).toList();

       // Primary check as all object should be of business type 
       // and if nothing exist we throw an exception
       if (listOfObjects.isEmpty()) {
           throw new RuntimeException("NO BUSINESS OBJECT FOUND");

       }

       // All objects are now of business type but we want them to be active
       List<CustomObject> listOfActiveObjects = listOfObjects.stream()
                     .filter(object -> object.objectStatus().equals("ACTIVE"))
                     .toList();

       // If no active object found just return the first business object sorted url

       if (listOfActiveObjects.isEmpty()) {
           return listOfObjects.stream()
                .sorted(Comparator.comparing(CustomObject::url))
                .toList().get(0).getUrl();
       }

       // Active objects are present so now filtered with proper locale

       List<CustomObject> listOfActiveObjectsWithLocale = listOfActiveObjects.stream()
                    .filter(object -> object.locale().equals("en-US"))
                    .toList();

       // If no locale was found just return the first sorted business active url

       if (listOfActiveObjectsWithLocale.isEmpty()) {
           return listOfActiveObjects.stream()
                 .sorted(Comparator.comparing(CustomObject::url))
                 .toList().get(0).getUrl();
       }

       // All filters applied, so within these objects return the sorted business/active/locale url
       return listOfActiveObjectsWithLocale.stream()
              .sorted(Comparator.comparing(CustomObject::url))
              .toList().get(0).getUrl();
   }
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете попробовать это.

     listOfObjects.stream()
            .filter(object -> object.objectType().equals("BUSINESS"))
            .min(
                Comparator.<CustomObject, Boolean>comparing(object -> object.getObjectStatus().equals("ACTIVE"))
                    .thenComparing(object -> object.getLocale().equals("en-US"))
                    .thenComparing(CustomObject::getUrl)
            )
            .map(CustomObject::getUrl)
            .orElseThrow(() -> new RuntimeException("NO BUSINESS OBJECT FOUND"));

ух ты! Спасибо! Но, похоже, он не пропускает случай, когда присутствует только БИЗНЕС и второй фильтр не проходит. Надо просто сортировать без фильтрации. Ниже я получаю zbc.com, когда ожидаю jsdf.com listOfObjs.add(new CustomObject("jsdf.com ", "BUSINESS", "NOACTIVE", "en-US"); listOfObjs.add(new CustomObject(" zbc.com", "BUSINESS", "NOACTIVE", "en-US");

Saad 21.08.2024 08:11

Возможно, вам придется поменять местами некоторые комараторы.

talex 21.08.2024 08:15

Думаю, я исправил твою проблему.

talex 21.08.2024 08:27

Спасибо, чувак! Но теперь он не проходит еще одно испытание! Это когда локаль не проходит, например listOfObjs.add(new CustomObject("jsdf.com ", "BUSINESS", "ACTIVE", "en-BR"); listOfObjs.add(new CustomObject(" ddddeee.com ", "NO-BUSINESS", "ACTIVE", "pl-PL")); listOfObjs.add(new CustomObject(" mmmm.com ", "БИЗНЕС", "АКТИВ", "без локали"); listOfObjs.add(new CustomObject(" test.com", "BUSINESS", "NOACTIVE", "en-US");

Saad 21.08.2024 08:32

Он рассматривает test.com выше, хотя этого не следует делать, потому что он НЕАКТИВЕН.

Saad 21.08.2024 08:37

Думаю, я это исправил. Проверьте еще раз.

talex 21.08.2024 09:00
Ответ принят как подходящий

Сначала проверьте наличие бизнес-объектов, а затем отсортируйте их по приоритету.

public static String transform(List<CustomObject> listOfObjects) {

    // Check if there are any "BUSINESS" objects in the list
    if (listOfObjects.stream().noneMatch(object -> object.objectType().equals("BUSINESS"))) {
        throw new RuntimeException("NO BUSINESS OBJECT FOUND");
    }

    // Sort the objects based on the desired criteria and return the first one
    return listOfObjects.stream()
        .sorted(Comparator
            .comparing((CustomObject object) -> !object.objectType().equals("BUSINESS")) // BUSINESS first
            .thenComparing(object -> !object.objectStatus().equals("ACTIVE")) // then ACTIVE
            .thenComparing(object -> !object.locale().equals("en-US")) // then locale en-US
            .thenComparing(CustomObject::getUrl) // finally by URL
        )
        .findFirst()
        .get()  // Since an element is guaranteed, we can safely call get()
        .getUrl();
}

Редактировать

Сейчас удаленный комментарий относился к вызову Optional.get() Поскольку в условии if мы убедились, что существует хотя бы один бизнес-объект, я не думаю, что это плохо. Но если вы предпочитаете, вы можете изменить его на что-то вроде

public String transform(List<CustomObject> listOfObjects) {

if (listOfObjects.stream().noneMatch(object -> object.objectType().equals("BUSINESS"))) {
    throw new RuntimeException("NO BUSINESS OBJECT FOUND");
}

return listOfObjects.stream()
    .sorted(Comparator
        .comparing((CustomObject object) -> !object.objectType().equals("BUSINESS"))
        .thenComparing(object -> !object.objectStatus().equals("ACTIVE"))
        .thenComparing(object -> !object.locale().equals("en-US"))
        .thenComparing(CustomObject::url)
    )
    .findFirst()
    .map(CustomObject::getUrl)
    .orElseThrow(() -> new RuntimeException("Unexpected error during transformation"));
}

Это работает! Спасибо! Но я думаю, что, как упоминал вышеприведенный комментатор, было бы гораздо лучше объединить исключение с оператором возврата вместо использования get().

Saad 21.08.2024 08:48

@Саад отредактировал мой ответ

Asmir 21.08.2024 09:07

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