Можно ли сократить код с помощью цикла?

Можно ли сократить такой код, например, с помощью цикла?

boolean isMorning = valueLn.text().contains("Утро");
boolean isDay =valueLn.text().contains("День");
boolean isEvening =valueLn.text().contains("Вечер");
boolean isNight =valueLn.text().contains("Ночь");
if (isMorning){ iterationCount = 3; }
else if (isDay) {iterationCount = 2;}
else if (isEvening){iterationCount =1;}
else if (isNight){iterationCount = 0;}

Ответы (1 шт):

Автор решения: Nowhere Man

Исходный код следует не "уменьшить"/сократить, а упростить -- убрать повторяющиеся элементы, и сократить логические операторы, в том числе и с помощью циклов или Stream API.
К примеру, нет необходимости вызывать четыре раза метод contains и заводить четыре булевых переменных, если в дальнейшем результат определяется через if / else-if и зависит только от одного флажка.

Например, проще реализовать отдельное перечисление, которое обрабатывало бы входную строку и содержало необходимые данные:

public enum DayPart {
    MORNING("Утро", 3),
    DAY("День", 2),
    EVENING("Вечер", 1),
    NIGHT("Ночь", 0);

    private final String ruAlias;
    private final int iterationCount;

    private DayPart(String alias, int count) {
        this.ruAlias = alias;
        this.iterationCount = count;
    }

    public int getIterationCount() { return this.iterationCount;}

    public static DayPart byAlias(String alias) {
        for (var v : DayPart.values()) {
            if (alias.contains(v.ruAlias)) {
                return v;
            }
        }
        return null; // или выбросить исключение
    }
}

Соответственно, необходимые данные вынесены в отдельный класс и логика обработки строки вынесена в отдельный статический метод этого класса, где используется цикл.

Таким перечислением проще пользоваться.

int iterCount = DayPart.byAlias(valueLn.text()).getIterationCount();

Аналогично, вместо циклов можно было бы применить Stream API + Optional / OptionalInt, чтобы правильнее представить "пустое" значение, не найденное во входной строке alias.

// enum DayPart

public static OptionalInt countByAlias(String alias) {
    return Arrays.stream(DayPart.values())
        .filter(v -> alias.contains(v.ruAlias)) // Stream<DayPart>
        .findFirst()                            // Optional<DayPart>
        .map(v -> OptionalInt.of(v.iterationCount))
        .orElseGet(OptionalInt::empty);
}

Разумеется, если главная задача -- просто сократить код, можно обойтись и без отдельного класса, но всё равно следует вынести логику в отдельный метод:

public static getIterCount(String dayPart) {
    if (dayPart.contains("Утро")) { // лучше использовать некую именованную константу
        return 3;
    } else if (dayPart.contains("День")) {
        return 2;
    } else if (dayPart.contains("Вечер")) {
        return 1;
    }
    return 0; // значение по умолчанию, не только для ночи
}

Ещё один вариант с использованием обновлённого switch-выражения с сопоставлением шаблонов (Java 21+) и упрощённой логикой, когда 0 всегда возвращается по умолчанию:

public static int getIterCount(Object o) {
    return switch (o) {
        case String s when s.contains("Утро") -> 3;
        case String s when s.contains("День") -> 2;
        case String s when s.contains("Вечер") -> 1;
        default -> 0;
    };
}
→ Ссылка