В классе мы создавали класс расширяемого массива. Делая это, мы создали метод, в котором вы выполняли итерацию по массиву, а позже мы создали другой метод, который использовал тот же код для итерации по списку, но вместо вызова предыдущего метода мы переписали тот же фрагмент кода. Когда я спросил своего профессора, почему мы должны переписать код вместо вызова более раннего метода, содержащего тот же код, он сказал, что все сводится к эффективности. Как меняется эффективность между переписыванием фрагмента кода и вызовом метода с таким же точным кодом?

Код из класса

    private void checkSize(int index){
        if (index >= myArray.length){
            throw new ArrayIndexOutOfBoundsException();
        }
    }

    public void set(int index, T obj){

        if (index >= myArray.length){
            reinitalizeArray(index+1);
        }
        myArray[index] = obj;
    }

Зачем вам переписывать оператор if в set, если вы могли бы попытаться поймать, вызвав таким образом checkSize ()?

    private void checkSize(int index){
        if (index >= myArray.length){
            throw new ArrayIndexOutOfBoundsException();
        }
    }

    public void set(int index, T obj){

        try{
            this.checkSize(index);
            myArray[index] = obj;
        }catch (ArrayIndexOutOfBoundsException exception){
            reinitalizeArray(index+1);
        }
    }
0
JJ Stamp 21 Окт 2015 в 17:04

3 ответа

Лучший ответ

Ваш вариант «повторного использования» использует исключения для управления потоком.

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

Это также ужасно с точки зрения производительности, потому что, если возникает исключение, создается и инициализируется объект Exception, нормальный поток программы приостанавливается, и виртуальная машина начинает поиск подходящего блока catch, а затем возобновляет выполнение оттуда. Это также увеличивает нагрузку на сборку мусора, так как исключение нужно будет собрать позже.

Вызов проверки Size () в вашем предложении также полностью излишен, поскольку присвоение myArray[index] = obj; вызовет точно такое же исключение, если массив слишком мал.

0
Durandal 21 Окт 2015 в 15:27

Что ж, эффективность , конечно, выше, когда вы повторно используете свой код, потому что вам не нужно его переписывать, и вам нужно только один раз протестировать.

Производительность может быть разной в зависимости от реализации списка. Если это ArrayList, он не должен сильно меняться. Если это другая реализация, это может иметь огромное значение. Допустим, вы использовали LinkedList. Каждый вызов get (index) будет перебирать весь список до тех пор, пока не будет достигнут элемент индекса, в то время как тот же вызов массива или ArrayList будет напрямую ссылаться на элемент и возвращать его. Или предположим, что вы используете вектор как реализацию. В этом случае синхронизация идет на первое место.

Вдобавок код будет как минимум отличаться в "получении" элементов: array [index] или list.get (index)

0
Mariano 21 Окт 2015 в 14:21

Код Java такой же, но сгенерированный код будет отличаться. Когда вы используете реальный тип (например, List или Vector), скомпилированный код будет содержать прямую ссылку на метод доступа ([]), но когда вы используете точно такой же код с универсальным типом (Enumeration), скомпилированный код будет содержать косвенные ссылки. поскольку сначала нужно получить реальный тип, а во-вторых - правильный метод доступа. Я лично считаю, что в большинстве случаев производительность, полученная таким образом, не стоит затраченных усилий. Делайте это кратко и просто.

0
Peter Krassoi 21 Окт 2015 в 14:19