Вопрос по java – CONSTANT.equals (VARIABLE) быстрее, чем VARIABLE.equals (CONSTANT)?

12

У меня был интересный разговор с одним из моих товарищей по команде.

ЯвляетсяCONSTANT.equals(VARIABLE) быстрее, чемVARIABLE.equals(CONSTANT) на Яве?

Я подозреваю, что это ложное утверждение. Но я пытаюсь понять, что за этим стоит качественная аргументация?

Я знаю, что в обоих случаях производительность не будет отличаться ни от одного существенного состояния. Но это была рекомендация по ЛУЧШЕЙ ПРАКТИКЕ, которая делает меня неудобным. Вот почему я ищу веские аргументы, которые я хочу представить в этом деле.

Пожалуйста помог

@ Йоахим Согласен, я должен был пометить его как связанный, не могу вернуть его сейчас Jigar Joshi
@ JigarJoshi: этот вопрос конкретно о скорости, а о связанном - нет. Joachim Sauer
Возможный дубликатInterview: Java Equals Jigar Joshi
У меня есть более важный вопрос: есть ли ситуации, когда (гипотетическая) разница будет иметь значение? Joachim Sauer
Разницы в производительности нет, но есть разница, пожалуйста, проверьте Stackoverflow.com / вопросы / 5712100 / интервью-ява-равно Jigar Joshi

Ваш Ответ

7   ответов
26

public class EqualsTest {
    public static String CONST = "const";
    public void constEqVar(String var) {
        CONST.equals(var);
    }
    public void varEqConst(String var) {
        var.equals(CONST);
    }
}

Затем я скомпилировал его, используя javac:javac EqualsTest.java и разобрал его используяjavap: javap -c EqualsTest.

Вот соответствующий фрагмент вывода javap:

public void constEqVar(java.lang.String);
  Code:
   0:   getstatic       #2; //Field CONST:Ljava/lang/String;
   3:   aload_1
   4:   invokevirtual   #3; //Method java/lang/String.equals:(Ljava/lang/Object;)Z
   7:   pop
   8:   return

public void varEqConst(java.lang.String);
  Code:
   0:   aload_1
   1:   getstatic       #2; //Field CONST:Ljava/lang/String;
   4:   invokevirtual   #3; //Method java/lang/String.equals:(Ljava/lang/Object;)Z
   7:   pop
   8:   return

Как вы можете видеть, единственное различие между этими двумя методами заключается в порядке операций: getstatic и затем aload_1 в первом случае и aload_1 + getstatic во втором случае.

Довольно очевидно, что время выполнения не должно зависеть от этого порядка.

Единственная причина, чтобы предпочестьconst.equals(var) скорее, чемvar.equals(const) стоит избегатьNullPointerException.

14

например

"Hello".equals(a); // will never throw a NPE
a.equals("Hello"); // can throw an NPE.

Ты можешь предпочесть, чтобы он взорвался, когда аnull но обычно нет.

2

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

Одним из преимуществ Constant.equals (переменная) является то, что вы не можете иметь исключение NullPointerException для .equals

NullPointerException очень хорошо известна, поэтому я в основном фокусируюсь на производительности. Ashish Agarwal
Производительность - это не то, чем JAVA известен вообщ Franz Ebner
@ Frank: 1. Java не является акрином, поэтому это «Java», 2. Даже если производительность невелика, соображения производительности могут все еще быть интересными (разница между «плохими» и «ужасными») и 3. Java довольно хороша в наши дни с производительностью, вы распространяете FUD. Joachim Sauer
@ Joachim Sauer 1. Я пишу на JAVA так, как хочу, есть ли у вас 76k или нет, 2. Говоря о производительности на JVM, работающей с (предположительно) DOS-NT-вложением (DOS & NT - аббревиатуры), фундаментально плотная, 3 Это сайт QA, и моя последняя запись была ответом, отличным от вашего. Franz Ebner
1

Сделайте простой тест со строками:

final String constHello = "Hello";
final int times = 1000000000;

long constTimeStart = System.nanoTime();

for (int i = 0; i < times; ++i) {
    constHello.equals("Hello");
}

long constTimeStop = System.nanoTime();

System.out.println("constHello.equals(\"Hello\"); " + times + " times: " + (constTimeStop - constTimeStart) + " ns");


constTimeStart = System.nanoTime();

for (int i = 0; i < times; ++i) {
    "Hello".equals(constHello);
}

constTimeStop = System.nanoTime();

System.out.println("\"Hello\".equals(constHello); " + times + " times: " + (constTimeStop - constTimeStart) + " ns");

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

Обратите внимание, что вы всегда будете сталкиваться с быстрым путем при сравнении, поскольку оба объекта на самом деле являются одними и теми же объектами. Кроме того, вы тестируете код, который не работает, потому что он не учитывает время прогрева. Joachim Sauer
@ Joachim Sauer: Вы правы. Имело неполное понимание того, как сделать эти тесты. Спасибо за разъяснение Mats Adborn
1

Если мы сравнимлюч @CONSTANT (левая часть метода equals) с любогоObject (правая часть метода equals) тогда компилятор может проверить сравнение и дать ожидаемый результат, но если мы сделаем наоборотObject ((Левая часть метода equals)) в сравнении с Постоянный ключ ((правая часть метода equals)) тогда ваша программа может черезИСКЛЮЧЕНИЕ НУЛЕВОГО УКАЗАТЕЛ.

public static void main(String[] args) {
        String CONSTANT_KEY = "JAVA";
        String string = null;

        // CASE 1
        if (CONSTANT_KEY.equals(string)) {
            System.out.println("I am in if block");
        }

        // CASE 2   
        if (string.equals(string)) {
            System.out.println("I am in if block");
        }
    }

В приведенном выше примере кода 1 всегда безопасно сравнивать объекты, чтобы исключить исключение NULL POINTER вместо случая 2.

0

код в java.langString поддерживает мой ответ.

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = count;
            if (n == anotherString.count) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = offset;
                int j = anotherString.offset;
                while (n-- != 0) {
                    if (v1[i++] != v2[j++])
                        return false;
                }
                return true;
            }
        }
        return false;
    }
Это выглядит довольно симметрично для меня ... assylias
Это симметрично, только если anObject является строкой ... tibo
@ tibo Не могли бы вы уточнить ваше последнее утверждение. Ashish Agarwal
Если это не строка, это означает, что ее метод равно отличается и поэтому может быть не симметричным tibo
0

private static String EXAMPLE = "Example";
private String obj = null;

Случай 1

if(obj.equals(EXAMPLE) {
}

Это исключение броска нулевого указателя ..

case 2:

if(EXAMPLE.equals(obj)) {
}

Это не сгенерирует исключение нулевого указателя ..

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