Java: если по сравнению с переключателем

Отладчики - это костыль.

Это настолько противоречиво, что даже я не верю в это так, как раньше.

Con: Я трачу больше времени на то, чтобы быстро освоить объемный код других людей, поэтому все, что поможет с «как я сюда попал» и «что происходит», может быть полезным до или после смерти.

Pro: Тем не менее, я с радостью поддерживаю идею, что если вы не понимаете ответы на эти вопросы для кода, который вы разработали сами или с которым вы знакомы, то все ваше время в отладчике не является Решение, это часть проблемы.

Прежде чем нажать «Опубликовать свой ответ», я быстро проверил в Google эту точную фразу, оказалось, что я не единственный, кто придерживался этого мнения или использовал эту фразу. Я поднял долгое обсуждение этого самого вопроса на форуме по программному обеспечению Fog Creek, на котором в качестве заметных сторонников упоминались разные светила, в том числе Линус Торвальдс

.

17
задан BalusC 9 May 2010 в 05:16
поделиться

11 ответов

В байт-коде есть две формы переключателя: tablewitch и lookupswitch . Один предполагает плотный набор ключей, другой - редкий. См. Описание переключателя компиляции в спецификации JVM . Для перечислений находится порядковый номер, а затем код продолжается как случай int . Я не совсем уверен, как будет реализована предлагаемая переключение на String небольшую функцию в JDK7.

Однако часто используемый код обычно компилируется в любой разумной JVM. Оптимизатор не совсем тупой. Не беспокойтесь об этом и следуйте обычной эвристике для оптимизации.

21
ответ дан 30 November 2019 в 10:08
поделиться

Не беспокойтесь о производительности; используйте синтаксис, который лучше всего выражает то, что вы делаете. Только после того, как вы: (а) продемонстрировали недостаточную производительность; и (б) локализовал его для рассматриваемой процедуры, только тогда вы можете беспокоиться о производительности. За мои деньги здесь более уместен синтаксис case.

24
ответ дан 30 November 2019 в 10:08
поделиться

Похоже, вы перечислили значения, поэтому, возможно, перечисление в порядке?

enum BRANCH {
  A,B, ... Y,Z;
}

Затем в вашем коде:

BRANCH branch = BRANCH.valueOf( WORD[ INDEX ] );

Кроме того, в вашем коде есть возможная ошибка, где "A" == " " может быть ложным в зависимости от идентичности объекта" A ".

7
ответ дан 30 November 2019 в 10:08
поделиться

Не совсем ответ на ваш вопрос, но на самом деле в вашем коде есть ошибка , у вас должен быть перерыв после каждого случая:

switch ( WORD[ INDEX ] ) {
    case 'A' : branch = BRANCH.A; break;
    /* B through to Y */
    case 'Z' : branch = BRANCH.Z; break;
}

Я не думаю, что разница в производительности здесь будет слишком значительной, но если вы действительно заботитесь о производительности и если этот код выполняется очень часто, вот другой вариант:

// Warning, untested code.
BRANCH[] branchLookUp = {BRANCH.A, BRANCH.B, ..., BRANCH.Z};

branch = branchLookUp[WORD[INDEX] - 'A'];

Обязательно инкапсулируйте это и хорошо задокументируйте.

4
ответ дан 30 November 2019 в 10:08
поделиться

Честно говоря, я не думаю, что в данном случае производительность имеет значение. Это действительно зависит от компилятора и его оптимизации.

3
ответ дан 30 November 2019 в 10:08
поделиться

Вот способ избежать всех операторов case.

import java.util.HashMap;

public class Dictionary {
    private static Dictionary                       ROOT;
    private boolean                                 terminus;
    private final HashMap<Character, Dictionary>    dictionaries    = new HashMap<Character, Dictionary>();

    private void ensureBranch(char c) {
        if (getBranch(c) != null)
            return;
        dictionaries.put(c, new Dictionary());
    }

    private Dictionary getBranch(char c) {
        return dictionaries.get(c);
    }

    public static boolean is(final String string) {
        ensureRoot();
        return is(chars(string), ROOT, 0, string.length() - 1);
    }

    public static void add(final String... strings) {
        ensureRoot();
        for (final String string : strings)
            add(chars(string), ROOT, 0, string.length() - 1);
    }

    private static void ensureRoot() {
        if (ROOT == null)
            ROOT = new Dictionary();
    }

    private static char[] chars(final String string) {
        return string.toUpperCase().toCharArray();
    }

    private Dictionary() {
        this.terminus = false;
    }

    private static void add(final char[] word, final Dictionary dictionary, final int index, final int limit) {
        Dictionary branch = getBranch(word, dictionary, index);
        if (index == limit)
            branch.terminus = true;
        else
            add(word, branch, index + 1, limit);
    }

    private static Dictionary getBranch(final char[] word, final Dictionary dictionary, final int index) {
        final char c = word[index];
        dictionary.ensureBranch(c);
        return dictionary.getBranch(c);
    }

    private static boolean is(final char[] word, final Dictionary dictionary, final int index, final int limit) {
        Dictionary branch = dictionary.getBranch(word[index]);
        if (branch == null)
            return false;
        if (index == limit)
            return branch.terminus;
        return is(word, branch, index + 1, limit);
    }
}
3
ответ дан 30 November 2019 в 10:08
поделиться

Если у вас есть оператор switch с последовательными целыми значениями, в зависимости от языка, он может быть оптимизирован до ветки стол, что очень быстро. Во всяком случае, он не медленнее!

Кроме того, использование if / else if было бы улучшением по сравнению с if для таких случаев, как этот, когда ваши случаи являются взаимоисключающими. Нет смысла делать еще 25 проверок после сопоставления A.

Но в основном любая разница в производительности незначительна, и вам следует использовать наиболее правильный синтаксис, которым в данном случае является оператор switch. Однако не забудьте разделить дела с перерывами.

3
ответ дан 30 November 2019 в 10:08
поделиться

Оператор switch должен использовать хэш, чтобы выбрать, к какому случаю перейти. Оттуда каждый последующий case также будет запускаться, если нет операторов break . Например, с вашим кодом, если вы включите X, он немедленно перейдет к X, затем Y, затем Z. См. Руководство по Java .

1
ответ дан 30 November 2019 в 10:08
поделиться

Я думаю, что это больше вопрос стиля, а не производительности. Я думаю, что в этом случае оператор switch более уместен, чем if. Не уверен, что есть большая разница в производительности.

0
ответ дан 30 November 2019 в 10:08
поделиться

Переключатель должен быть логарифмическим, а if линейным, если компилятор не может найти ничего умного. Но длинные переключатели сложны для чтения, а также подвержены ошибкам - как уже отмечалось, переключатель, который у вас выше, не имеет разрывов, и он будет проваливаться во всех случаях.

Почему бы вместо этого не предварительно заполнить Map , а просто использовать Map.get () ?

private static final Map<Char, Whatever> BRANCHES = Collections.unmodifiableMap(new HashMap<Char, Whatever>() {{
    put('A', BRANCH.A);
    ...
    put('Z', BRANCH.Z);
}}

public void getBranch(char[] WORD, int INDEX) {
    return BRANCHES.get(WORD[INDEX]);
}

Как отмечалось выше, если BRANCH является Enum , это поведение должно быть правильно в Enum .

(Что такое WORD , ИНДЕКС и ФИЛИАЛ все равно здесь? Судя по именам, они должны быть константами, но у вас не может быть постоянных массивов - содержимое всегда можно изменять; не было бы особого смысла создавать постоянную «структуру»; и, конечно, не было бы особого смысла в iffing или переключении на основе констант ....)

1
ответ дан 30 November 2019 в 10:08
поделиться

Я знаю, что вы совсем не об этом спрашиваете, но разве вы не делаете это просто так?

public class Dictionary {
    private static final Set<String> WORDS = new HashSet<String>();

    public static void add(final String... STRINGS) {
        for (String str : STRINGS) {
            WORDS.add(str.toUpperCase());
        }
    }

    public static boolean is(final String STRING) {
        return WORDS.contains(STRING.toUpperCase());
    }
}

Вы просто ищете что-то более эффективное с точки зрения памяти?

2
ответ дан 30 November 2019 в 10:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: