У меня есть следующий метод, который принимает список 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();
}




Вы можете попробовать это.
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"));
Возможно, вам придется поменять местами некоторые комараторы.
Думаю, я исправил твою проблему.
Спасибо, чувак! Но теперь он не проходит еще одно испытание! Это когда локаль не проходит, например 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");
Он рассматривает test.com выше, хотя этого не следует делать, потому что он НЕАКТИВЕН.
Думаю, я это исправил. Проверьте еще раз.
Сначала проверьте наличие бизнес-объектов, а затем отсортируйте их по приоритету.
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().
@Саад отредактировал мой ответ
ух ты! Спасибо! Но, похоже, он не пропускает случай, когда присутствует только БИЗНЕС и второй фильтр не проходит. Надо просто сортировать без фильтрации. Ниже я получаю zbc.com, когда ожидаю jsdf.com listOfObjs.add(new CustomObject("jsdf.com ", "BUSINESS", "NOACTIVE", "en-US"); listOfObjs.add(new CustomObject(" zbc.com", "BUSINESS", "NOACTIVE", "en-US");