Как проверить, есть ли значение параметра в списке констант - PullRequest
1 голос
/ 22 февраля 2010

У меня есть список констант, и я хочу проверить, равно ли значение, переданное методу, одной из констант. Я знаю Enums, что было бы хорошо, но мне нужно значение int здесь из соображений производительности. У перечисляемых значений может быть значение, но я боюсь, что получить значение int медленнее, чем напрямую использовать int.

public static final int 
  a = Integer.parseInt("1"), // parseInt is necessary in my application
  b = Integer.parseInt("2"), 
  c = Integer.parseInt("3");

public void doIt(int param) {
  checkIfDefined(param);
  ...
}

Вопрос о checkIfDefined. Я мог бы использовать if:

if(param == a)
  return;
if(param == b)
  return;
if(param == c)
  return
throw new IllegalArgumentException("not defined");

Или я мог бы использовать Arrays.binarySearch(int[] a, int key), или ... любую лучшую идею?

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

Решение

Поскольку enum или switch работали в моем специальном случае с parseInt, я теперь использую простые старые int-константы вместе с Arrays.binarySearch.

Ответы [ 5 ]

1 голос
/ 22 февраля 2010

Если ваш список констант длинный, загрузите их в HashSet. Это даст вам самое быстрое время поиска: все обращения к хэш-картам выполняются за время O (1) (и с небольшими постоянными затратами, кроме автоматической упаковки целого числа).

Если ваш список констант является коротким и инвариантным, используйте оператор switch и позвольте компилятору по существу создать для вас HashSet (без автобоксирования).

Если он где-то посередине, выбросить их в массив, отсортировать и использовать Arrays.binarySearch. Вы можете сделать около 5-10 сравнений за время, которое требуется для упаковки одного целого числа, поэтому я бы переключился на HashSet, как только число достигнет сотен.

Если оно очень короткое, и вы знаете, какое число, скорее всего, появится, закодируйте его вручную в операторах if, сначала проверив самые распространенные.

1 голос
/ 22 февраля 2010

Я вполне уверен, что получение значения свойства int для перечисления примерно так же быстро, как получение значения для константы типа int. (Но если вы сомневаетесь, почему бы не создать прототип и не измерить производительность обоих решений?) Использование enum s делает ваш код намного более читабельным, оно всегда стоит таких небольших дополнительных усилий.

Для быстрого поиска, если у вас есть только целочисленные значения без знака, вы можете сохранить значения перечисления в ArrayList, проиндексированном их соответствующим значением int.

1 голос
/ 22 февраля 2010

Предпочитаете ли вы использовать перечисления:

public enum Letters {
    A("1"), B("2"), C("3");

    private final String value;

    private Letters(String value) {
        this.value = value;
    }

    public Letters getByValue(String value) {
        for (Letters letter : values()) {
            if (letter.value.equals(value)) return letter;
        }
        throw new IllegalArgumentException("Letter #" + value + " doesn't exist");
    }

    public int toInt() {
        return Integer.parseInt(value);
    }
}
0 голосов
/ 22 февраля 2010

Полагаю, что решение для массива, которое вы выложили, постится до тех пор, пока количество параметров остается небольшим. Если он становится больше 128 и вам нужно это часто, то я бы выбрал HashSet:

Set<Integer> params = new HashSet<Integer>();
params.add(Integer.valueOf("1"));
params.add(Integer.valueOf("2"));
params.add(Integer.valueOf("3"));

public boolean checkIfDefined(int param){
    return params.contains(param);
}

Автобокс, конечно, медленный, но поиск хеша O (1), а не O (log n) как бинарный поиск.

2.) Быстрое решение, если память не так важна или параметры не доходят до высокого значения, - это использование логического [] с использованием параметров в качестве индекса:

boolean[] params = new boolean[MAX_PARAMS+1];
params[Integer.parseInt("1")] = true;
params[Integer.parseInt("2")] = true;
params[Integer.parseInt("3")] = true;

public boolean checkIfDefined(int param){
    if (param < 0 || params.length <= param)
        return false;
    return params[param];
}
0 голосов
/ 22 февраля 2010

Как насчет оператора switch . Вы можете выдать исключение в случае по умолчанию .

...