I have this following method that takes in a List of a CustomClass and performs filters using streams and returns at each step based on the result of the filter.
I was wondering if there was a way to simplify the code but combining the filters and statements together to make it more concise and efficient.
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();
}
Check for Business objekts first then sort by your priority
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();
}
Edit
The now deleted comment was refering to calling Optional.get()
Since in the if condition we made sure that there is at least one Business object, I don't think it is bad. But if you prefer you can change it to something like
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"));
}