Жаба - оптимизация + вынос кода в отдельный метод класса

Тема в разделе "WASM.ZEN", создана пользователем volodya, 19 апр 2005.

  1. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Люди добрые, у мя уже запор. Смотрю в книгу, вижу фигу.

    Есть вот такой код на жабе:


    Код (Text):
    1.  
    2.                 int index = Integer.parseInt(m.group(3));
    3.                 int size = bg.getAlleleList().getSize();
    4.                 if(index > size)
    5.                 {
    6.                     if(size == -1)
    7.                     {
    8.                         for(int i = 0; i <= index; i++)
    9.                         {
    10.                             bg.getAlleleList().addBean(new AlleleBean());
    11.                         }
    12.                     }
    13.                     else
    14.                     {
    15.                         for(int i = size + 1; i <= index; i++)
    16.                         {
    17.                             bg.getAlleleList().addBean(new AlleleBean());
    18.                         }
    19.                     }
    20.                 }
    21.  




    и этот вот:


    Код (Text):
    1.  
    2.                 int size = gen_experiment.getGenExpResultList().getSize();
    3.                
    4.                 if(index > size)
    5.                 {
    6.                     if(size == -1)
    7.                     {
    8.                         for(int i = 0; i <= index; i++)
    9.                         {
    10.                             gen_experiment.getGenExpResultList().addBean(new GeneticExpResultBean());
    11.                         }
    12.                     }
    13.                     else
    14.                     {
    15.                         for(int i = size + 1; i <= index; i++)
    16.                         {
    17.                             gen_experiment.getGenExpResultList().addBean(new GeneticExpResultBean());
    18.                         }
    19.                     }
    20.                 }
    21.  




    Теперь вопросы.

    1. Вопрос первый - это как бы оптимизировать это дело. Я уже просто затуркался и, наверное, не вижу очевидного. Там два цикла, как видите. Общий смысл процедуры прост - если индекс перешкаливает текущий размер, стал быть, массив расширяется до границ индекса. Заранее я его создать не могу - я не знаю, сколько там будет элементов. Создать и удалять ненужные тоже сложно по ряду причин. Словом, надо привязываться к этой модели.



    2. Хотелось бы вычленить этот код в функцию. Такой код у мя используется во многих хендлерах (около 14 штук), поэтому его имеет смысл оформить как отдельный класс - хелперный там какой-нибудь. Посему вопрос. Костяк кода-то один и тот же, а вот элементы пихаются разные.


    Код (Text):
    1.  
    2. gen_experiment.getGenExpResultList().addBean(new GeneticExpResultBean());
    3.  




    или


    Код (Text):
    1.  
    2. bg.getAlleleList().addBean(new AlleleBean());
    3.  




    Скажем, как создать некую функцию prefill()? передавать ей размер ArrayList, индекс... Но как разобраться с тем, что путь для заполнения каждый раз другой? И элемент другой?
     
  2. Stiver

    Stiver Партизан дзена

    Публикаций:
    0
    Регистрация:
    18 дек 2004
    Сообщения:
    812
    Адрес:
    Germany
    volodya





    Передавай имя класса и используй reflection, поиск по Class.forName() и Class.newInstance().
     
  3. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    volodya

    Так немного компактнее, т.к. -1 + 1 == 0:
    Код (Text):
    1. int index = Integer.parseInt(m.group(3));
    2. int size = bg.getAlleleList().getSize();
    3. if(index > size){
    4.    for(int i = size + 1; i <= index; i++){
    5.       bg.getAlleleList().addBean(new AlleleBean());
    6.    }
    7. }
     
  4. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    То, что возвращают gen_experiment.getGenExpResultList() и bg.getAlleleList() объявить воплощающими один интерфейс (а так оно и есть, наверное, раз оба имеют addBean) или наследующими от одного класса, например X. Тогда объект этого класса можно передавать в функцию:
    Код (Text):
    1. void prefill(int index,int size,X myObj,String myBean){
    2.    if(index > size){
    3.       for(int i = size + 1; i <= index; i++){
    4.          myObj.addBean(Class.newInstance(myBean));
    5.       }
    6.    }
    7. }


    И вызываем теперь так:
    Код (Text):
    1. prefill(Integer.parseInt(m.group(3)),bg.getAlleleList().getSize(),bg.g  etAlleleList(),"AlleleBean");
    2. prefill(?,gen_experiment.getGenExpResultList().getSize(),gen_experimen  t.getGenExpResultList(),"GeneticExpResultBean");
     
  5. Stiver

    Stiver Партизан дзена

    Публикаций:
    0
    Регистрация:
    18 дек 2004
    Сообщения:
    812
    Адрес:
    Germany
    Quantum





    Class.newInstance разве имеет аргументы? По крайней мере в 1.4 нужно Class.forName(myBean).newInstance(), или я ошибаюсь?
     
  6. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Stiver

    Конечно forName. Это я ошибся. Вообще reflection не люблю, вот и сморозил глупость.



    Ещё нужно try/catch добавить. Вот тутор.
     
  7. bsl_zcs

    bsl_zcs New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2003
    Сообщения:
    17
    Адрес:
    Karaganda, Kazakhstan
    Передавать имя класса строчкой - пошло. Во-первых, его потом по этому имени искать придётся в рантайме, что добавит тормозов и без того нешустрой жабе, а, во-вторых, теряется ссылка на использование класса, отчего всякие оболочки не будут показывать его в списке использований, и придётся искать ещё по строчкам.

    Лучше передавать сразу ссылку на отражение класса.



    prefill(bg.getAlleleList(), Integer.parseInt(m.group(3)), AlleleBean.class);


    Код (Text):
    1.     static void prefill(List lst, int size, Class c)
    2.     {
    3.         try
    4.         {
    5.             for(int i = lst.size(); i<size; i++)
    6.                 lst.add(c.newInstance());
    7.         }
    8.         catch(Exception e) { e.printStackTrace(); }
    9.     }
    10.  


    Листы у вас, судя по всему, нестандартные, поскольку стандартный лист, когда он пустой, возвращает 0 в качестве размера, да и метод называется size а не getSize, но раз volodya упоминал ArrayList, то я пример кинул для листов стандартных.



    Кстати, если все листы будут строго ArrayList-ами, или унаследоваными от него, можно будет несколько повысить производительность, расширив его один раз заранее.
    Код (Text):
    1.     static void prefill(ArrayList lst, int size, Class c)
    2.     {
    3.         lst.ensureCapacity(size);
    4.         try { // дальше так же...
    5.  




    А вообще, через reflection удобно такие вещи делать только если объект не требует инициализации кроме вызова конструктора без параметров. Если с ним надо хоть что-то делать кроме этого, лучше вынести создание элемента в factory-метод, и переопределять его анонимно.
     
  8. Stiver

    Stiver Партизан дзена

    Публикаций:
    0
    Регистрация:
    18 дек 2004
    Сообщения:
    812
    Адрес:
    Germany
    bsl_zcs





    Не знаю как Java 5, но компилятор 1.4 преобразует .class(по крайней мере первое обращение) в вызов того же самого Class.forName, так что дополнительных тормозов это не добавит. Другое дело, что уже имеющихся хватит за глаза :)







    согласен
     
  9. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Ого, сколько всего навалили :)

    А можно подробнее с момента "лучше вынести создание элемента в factory-метод, и переопределять его анонимно"? Это о паттерне Object factory?
     
  10. bsl_zcs

    bsl_zcs New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2003
    Сообщения:
    17
    Адрес:
    Karaganda, Kazakhstan
    Stiver



    Слушай, и правда, жаба 1.4 какую-то лажу лепит. Пятая такого себе не позволяет - грузит сразу ссылку на класс.



    Тем не менее, даже та конструкция, которую подставляет старая жаба, предназначена для ускорения работы. Там даже отдельное статическое поле используется для хранения ссылки, чтобы искать по имени её только один раз, а потом отдавать уже прокэшированное значение.
     
  11. bsl_zcs

    bsl_zcs New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2003
    Сообщения:
    17
    Адрес:
    Karaganda, Kazakhstan
    volodya





    Ага. Только вряд ли оно будет эффективнее или проще варианта с отражением конкретно в этом случае.