2010-03-23 1 views
2

ли переключатель заявление быстрый способ осуществить интерпретацию оператора в Javaесть переключатель заявлении, самый быстрый способ осуществить интерпретацию оператора в Java

public boolean accept(final int op, int x, int val) { 
    switch (op) { 
     case OP_EQUAL: 
      return x == val; 
     case OP_BIGGER: 
      return x > val; 
     case OP_SMALLER: 
      return x < val; 
     default: 
      return true; 
    } 
    } 

В этом простом примере, очевидно, да. Теперь представьте, что у вас 1000 операторов. будет ли он еще быстрее, чем иерархия классов? Есть ли порог, когда иерархия классов становится более эффективной по скорости, чем оператор switch? (в памяти, очевидно, нет)

abstract class Op { 
abstract public boolean accept(int x, int val); 
} 

А затем один класс на одного оператора.

EDIT: Извините, я должен был быть более конкретным по виду ответов. Оператор полностью неизвестен, и я использую JDk 1.4. Нет выбора. Нет перечислений. Нет закрытий. :( Оператор выбирается пользователем среди множества многих вариантов. Для простоты, представьте графический интерфейс с 1000 операций, когда пользователь выбирает один, выбирается операционный код оператора switch. Используя иерархию классов, пользователь будет выбирать a class. Я задаю этот вопрос, потому что кто-то должен был его протестировать раньше. Мне не хочется создавать 1000 классов и 1000 фиктивных оп-кодов для его проверки. Если никто этого не сделал, я буду тестировать его и сообщать о результатах , если они могут иметь какой-либо смысл.

+15

Не угадать. Мера. – skaffman

+1

профайлер мощность. Тем не менее, я бы подумал о том, чтобы хранить мои операторы в массиве методов, индексированных с помощью «op». – MonoThreaded

+1

. Enum кажется лучшей альтернативой, более читаемой и поддерживаемой с предопределенным набором операций. – Robin

ответ

2

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

я думаю, что сложно выполнить оператор switch. Из-за ограничений, которые Java ставит на типы, которые можно переключить, их довольно легко скомпилировать в таблицу поиска, которая касается быстрого доступа, который вы можете получить.

+0

ну, это также моя интуиция, что оператор switch является победителем даже хотя это плохой ООП. Мне все еще интересно, может ли решение метода подкласса превзойти его. => subClassOfAbstractOperator.operate (x, val); – Mordan

0

Если вызывающему методу уже необходимо решить, какое значение оператора использовать и вызвать accept(), то самым быстрым будет выполнение сравнения внутри одного и того же метода вызова.

Также можно использовать три метода (или стратегии):

public boolean acceptGreater(int x, int val) { 
    return x > val; 
} 

public boolean acceptLess(int x, int val) { 
    return x < val; 
} 

public boolean acceptEquals(int x, int val) { 
    return x == val; 
} 
0

Я бы не смотреть на это чисто с сырым точки зрения производительности, но я бы оценить это как рефакторинг кандидата, см c2:Refactor Mercilessly , Мне понравился ответ code resuability:

  1. Если вы повторите его один раз, скопируйте его.
  2. Если вы повторите это дважды, реорганизовать его.

Я бы определил добавление нескольких операторов case как повторение, а затем я бы реорганизовал для реализации Strategy Pattern.
Я бы назвал классы операторов суффиксом стратегии и реализовал метод execute.

8

Из-за того, что оператор switch обычно реализуется в jvm, с помощью таблицы поиска, скорее всего, он будет быстрее, с небольшим или большим числом операторов. Это просто догадки; чтобы получить определенный ответ, который вам нужен, чтобы сравнить его с системой, которую она должна запускать.

Но это всего лишь микро-оптимизация, о которой вы не должны заботиться, если профилирование не показывает, что это действительно может изменить ситуацию.Использование целых чисел вместо определенного класса (или перечисления) делает код менее читаемым. Огромный оператор switch с 1000 случаями - признак плохого дизайна. И это повлияет на код, который использует операторы; менее читаемый, больше ошибок, сложнее для рефакторинга, ...

И вернуться к производительности, которая, кажется, является целью здесь. В трудночитаемом, плохо разработанном коде изменения, необходимые для макрооптимизация, становятся сложнее. И эти оптимизации, как правило, много важнее, чем микро-оптимизации, такие как этот переключатель.

9

EDIT:

Хорошо, так как вы должны использовать JDK 1.4, мой первоначальный ответ является непроходной (слева внизу для справки). Я бы угадал, что switch не так быстро, как абстрактное решение на основе класса, когда вы просто смотрите на вызов apply(which,a,b) против which.apply(a,b). Тебе просто нужно это проверить.

Однако при тестировании, вы можете также рассмотреть вопрос о времени запуска, объем памяти и т.д.

ORIGINAL:

public enum OPERATION { 
    // ...operators+implementation, e.g.: 
    GREATER_THAN { public boolean apply(int a, int b) { return a > b; } }; 
    public abstract boolean apply(int a, int b); 
} 

использование:

OPERATION x = //..however you figure out which 
boolean result = x.apply(a,b); 

это один случай использует в эффективной Java для перечислений. Он работает точно так же, как switch, но менее запутанным.

+0

whoops- in Эффективная Java, не учебная тропа Java. – Carl

0

Я всегда находил, что инструкция оператора java не такая мощная, насколько мне нужно. В его last release lambdaj implements it с умным использованием закрытия и Hamcrest матчер.

1

Использование табличного метода, как указывалось в предыдущем посте, вы можете использовать оператор как индекс массива. Значение, хранящееся в массиве, может быть экземпляром класса, который выполняет сравнение. Массив может быть инициализирован статически или лучше по требованию (ленивый шаблон загрузки).

например.

// Interface and classes 
interface Operator { 
     boolean operate(int x, int y); 
} 

class EqualsOperator implements Operator { 
     boolean operate(int x, int y){ 
     return x==y; 
     } 
} 
class NotEqualsOperator implements Operator { 
     boolean operate(int x, int y){ 
     return x=!y; 
     } 
} 
... 

// Static initialization 
Operator[] operators = new Operator[n]; 
operator[0] = new EqualsOperator(); 
operator[1] = new NotEqualsOperator(); 
... 

// Switch 
public boolean accept(final int op, int x, int val) { 
    operator[op].operate(x,val); 
} 
+1

yea thx человек. но возникает вопрос: оператор оператор [op] .operate (x, val); быть быстрее, чем вся инструкция switch. – Mordan

+0

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

Смежные вопросы