I am not sure if I understood you correctly but as far as I got it is that you want to get all schools that either have empty classes or that have classes without students.
What you can do is defining the predicates outside of the stream.
Predicate<School> empty_students_filter = school ->
school.getSchoolClassList().stream().map(SchoolClass::getStudentList).anyMatch(List::isEmpty);
Predicate<School> empty_classes_filter = school -> school.getSchoolClassList().isEmpty();
Then you can use the predicates inside your filter method and combine them with Predicate.or():
List<School> schools_with_no_or_empty_classes =
schools.stream()
.filter(empty_classes_filter.or(empty_students_filter))
.collect(Collectors.toList());
Note: if you want to get only the schools that have classes and all classes should have students, then you can adapt the filter as follows with a Predicate.and():
.filter(Predicate.not(empty_classes_filter).and(Predicate.not(empty_students_filter)))
EDIT:
According to your comment, this is not easily doable using the Streams API because you iterate over a Collection of schools and you can only filter schools based on their properties and not filter their properties. So you would need to implement your own custom collector.
I would recommend solving the problem in 2 steps.
Step 1:
Remove all classes from a school that contain no students.
Step 2:
Stream over and collect all schools that have classes.
//step 1:
result.forEach(school -> {
List<SchoolClass> school_classes = school.getSchoolClassList();
List<SchoolClass> empty_classes =
school_classes.stream()
.filter(school_class -> school_class.getStudentList().isEmpty())
.collect(Collectors.toList());
school.getSchoolClassList().removAll(empty_classes);
});
//step 2:
List<School> remaining_schools = result.stream()
.filter(school -> !school.getSchoolClassList().isEmpty())
.collect(Collectors.toList());
.filter(cls-> cls.getStudentList().size() > 0), no need to stream that list.