我有一组对象,我想按照它们被迭代的顺序进行一些操作。在该操作被调用之后,我想对它们执行其他操作。基本上,代码看起来像这样:
for(int i = 0;i < myobj.size();i++)
{
myobj.at(i).doSomething();
}
for(int i = 0;i < myobj.size();i++)
{
myobj.at(i).doSomethingElse();
}
这对我来说看起来很难看。我怎么能把它重写成更好的东西?操作的顺序应该保持不变。
答案 0 :(得分:24)
我不知道myobj是什么,但如果它是Iterable
,那么你可以使用foreach循环:
for (Foo foo : myobj) {
foo.doSomething();
}
for (Foo foo : myobj) {
foo.doSomethingElse();
}
如果它不是Iterable
,那么这样做也可能有助于其他代码。
答案 1 :(得分:6)
如果绝对必须在不同的循环中进行这两个操作,请将循环重构为适当命名的方法,以便一目了然更容易理解:
createData();
saveData();
答案 2 :(得分:4)
使用foreach循环:
for (MyObject currentObject : myobj) {
currentObject.doSomething();
}
for (MyObject currentObject : myobj) {
currentObject.doSomethingElse();
}
答案 3 :(得分:3)
这看起来是您应用Visitor pattern的绝佳机会。
答案 4 :(得分:3)
答案 5 :(得分:2)
通过使用lambdaj,您可以获得相同的结果,而无需编写任何显式循环:
forEach(myobj).doSomething();
forEach(myobj).doSomethingElse();
答案 6 :(得分:1)
与其他产品略有不同:让您对方法的调用返回下一个要操作的项目,并使用明确定义的终止返回(例如,null
):
while ((holder = holder.doSomething())!=null);
while ((holder = holder.doSomethingElse())!=null);
显然,有一些初步和干预重新分配持有人。赞成访客建议,实现Iterable也是一个不错的选择;我的解决方案也可以被视为使用myObj实现Iterator:
while (myObj.hasNext()) myObj.next().doSomething();
myObj.resetIterator();
while (myObj.hasNext()) myObj.next().doSomethingElse();
一个缺点是,如果你达到了doSomething()和doSomethingElse()可以在一个循环中应用的点,而不是两个独立的循环,你必须有一个合并的方法来使这个工作并利用那种变化。
for-loop上的替代方案,使用后修复(实际上受到那种可怕的混淆解决方案的启发):
int size = myObj.size(), i=0;
while (i<size) myObj.at(i++).doSomething();
i=0;
while (i<size) myObj.at(i++).doSomethingElse();
并且,如果只有doSomething()on all和doSomethingElse()的所有事项的顺序(即,不是访问它们的索引顺序),你甚至可以跳过中间的重新分配,并且只是预先修复第二次调用的减量。
int size = myObj.size(), i=0;
while (i<size) myObj.at(i++).doSomething();
while (i>0) myObj.at(--i).doSomethingElse();
当然,如果myObj实现了ListIterator而不是Iterator,那么上面的Iterator解决方案的版本更加性感(好吧,我现在停止编辑更多的东西......认真)。
答案 7 :(得分:0)
你可以像
一样做同样丑陋的事情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;}
}
答案 8 :(得分:0)
这是另一种写作方式。
我认为,这是访客模式,虽然我一直看到它但我不太明白(访客文档)所以,这可能是其他的。
无论如何,我们的想法是使用匿名内部类(假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
迭代项目“noise”
为什么你可以做this?
因为这样你可以有一系列的操作:
_ [] 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
答案 9 :(得分:-3)
for(int i = 0;i < myobj.size();i++)
{
myobj.at(i).doSomething();
myobj.at(i).doSomethingElse();
}