Как вы пишете эти циклы в Java лучше? - PullRequest
3 голосов
/ 31 октября 2009

У меня есть набор объектов, над которыми я хотел бы выполнить некоторые операции, в порядке их повторения. После того, как им будет вызвана эта операция, я бы хотел выполнить над ними другие операции. По сути, код будет выглядеть примерно так:

for(int i = 0;i < myobj.size();i++)
{
   myobj.at(i).doSomething();
}

for(int i = 0;i < myobj.size();i++)
{
   myobj.at(i).doSomethingElse();
}

Это выглядит уродливо для меня. Как я мог переписать это во что-то лучшее? Порядок операций должен оставаться прежним.

Ответы [ 10 ]

24 голосов
/ 31 октября 2009

Я не знаю, что такое myobj, но если это Iterable, то вы можете использовать цикл foreach:

for (Foo foo : myobj) {
  foo.doSomething();
}

for (Foo foo : myobj) {
  foo.doSomethingElse();
}

Если это не Iterable, то его создание может помочь и другому коду.

6 голосов
/ 31 октября 2009

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

createData();
saveData();
4 голосов
/ 31 октября 2009

Используйте цикл foreach:

for (MyObject currentObject : myobj) {
  currentObject.doSomething();
}

for (MyObject currentObject : myobj) {
  currentObject.doSomethingElse();
}
3 голосов
/ 31 октября 2009
3 голосов
/ 31 октября 2009

Это выглядит как отличная возможность применить шаблон Visitor .

2 голосов
/ 10 ноября 2009

Используя lambdaj , вы можете получить тот же результат без записи какого-либо явного цикла, как показано ниже:

forEach(myobj).doSomething();
forEach(myobj).doSomethingElse();
1 голос
/ 31 октября 2009

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

while ((holder = holder.doSomething())!=null);
while ((holder = holder.doSomethingElse())!=null);

С некоторой первоначальной и промежуточной переназначением владельца, очевидно. Отмечаем предложение посетителя, реализация Iterable также является хорошим вариантом; моё решение также можно рассматривать как реализацию Iterator с myObj:

while (myObj.hasNext()) myObj.next().doSomething();
myObj.resetIterator();
while (myObj.hasNext()) myObj.next().doSomethingElse();

Один недостаток - если вы когда-нибудь дошли до того, что doSomething () и doSomethingElse () могут быть применены в одном цикле, вместо двух отдельных, вы должны иметь объединенный метод, чтобы сделать эту работу и воспользоваться преимуществами это изменение.

Альтернатива цикла for, использующая пост-исправление (на самом деле вдохновленное этим ужасным, запутывающим решением):

int size = myObj.size(), i=0;
while (i<size) myObj.at(i++).doSomething();
i=0;
while (i<size) myObj.at(i++).doSomethingElse();

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

int size = myObj.size(), i=0;
while (i<size) myObj.at(i++).doSomething();
while (i>0) myObj.at(--i).doSomethingElse();

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

0 голосов
/ 31 октября 2009

Это альтернативный способ написания того же.

Я думаю, что это шаблон посетителя, хотя я все время видел его, я не совсем понимаю (документация посетителя), так что, вероятно, это что-то другое.

В любом случае, идея состоит в том, чтобы использовать анонимные внутренние классы (поддельные Java "замыкания" ) и написать итерацию один раз.

public class IterationSample {
    public static void main( String [] args ) {

        Foo [] items = new Foo[0]; // get it from somewhere  ....

        iterate( items , new _(){void with( Foo f ){
            f.doSomething();
        }});    

        iterate( items , new _(){void with( Foo f ){
            f.doSomethingElse();
        }});    

        iterate( items , new _(){void with( Foo f ){
            f.doBar();
        }});   



    }
    // write  the loop once.
    static void iterate( Foo [] items, _ visitor ) {
        for( Foo f : items ) {
            visitor.with( f );
        }
    }
}

Объект Foo будет объектом, который будет вашим объектом.

// Not really abstract just for the sake of the sample. Use your own.
abstract class Foo {
    abstract void doSomething();
    abstract void doSomethingElse();
    abstract void doBar();

}

Наконец-то это «посетитель»

// made abstract instead of interface just to avoid having to type 
// "public" each time. 
abstract class  _ {
    abstract void with( Foo f );
}

Жаль, что я не могу избежать возвращаемого типа метода.

В противном случае это

         iterate( items ,new _(){ with( Foo f ){ 

будет читаться как:

Повторять элементы "шум" с помощью foo

Зачем вам это делать, когда вы можете сделать это ?

Потому что таким образом вы можете иметь массив операций:

 _ [] operations = {
        new _(){void with( Foo f ){
            f.doSomething();
        }},
        new _(){void with( Foo f ){
            f.doSomethingElse();
        }},
        new _(){void with( Foo f ){
            f.doBar();
        }}
 };

И повторять их :)

  for( _ andPerformAction : operations ) {
      iterate( items , andPerformAction );
  }

Могут быть некоторые ситуации для этого, хотя я могу думать о любой прямо сейчас = -S

0 голосов
/ 31 октября 2009

Вы всегда можете сделать что-то столь же безобразное, как

bool d=false;
for(int i = 0;i < myobj.size();i++)
{
   if(d==false){
     myobj.at(i).doSomething();
   }else{
     myobj.at(i).doSomethingElse();
   }
   if(i==myobj.size()-1 && d==false){ d=true; i=0;}
}
0 голосов
/ 31 октября 2009

ммм, это будет работать для вас?

for(int i = 0;i < myobj.size();i++)
{   
    myobj.at(i).doSomething();
    myobj.at(i).doSomethingElse();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...