Если вы собираетесь придерживаться JVM ниже 1,8, тогда ваш код в порядке!
Возможно, вы могли бы пропустить несколько операций, таких как разрыв цикла, когда вы нашли совпадение для трех логических значений, и проверка толькоте, которые еще не найдены.
for (ItemType item : items) {
hasX = hasX || doesHaveX(item);
hasY = hasY || doesHaveY(item);
hasZ = hasZ || doesHaveZ(item);
if (hasX && hasY && hasZ) {
break;
}
}
Если вам просто хорошо использовать потоки, возможно, лучше инициализировать каждую переменную при ее создании следующим образом:
boolean hasX = items.stream().anyMatch(this::doesHaveX); // goes trough the elements until a match is found.
boolean hasY = items.stream().anyMatch(this::doesHaveY); // goes trough the elements until a match is found.
boolean hasZ = items.stream().anyMatch(this::doesHaveZ); // goes trough the elements until a match is found.