如果您使用函数式编程,可以重复使用此代码。有许多库可以为您编写大量的代码。在这个例子中,我只是使用了Guava(http://code.google.com/p/guava-libraries/),但像Functional Java(http://functionaljava.org/)这样的库同样适用。
函数式编程的一个主要优点是能够将算法抽象化,以便您可以在需要的任何地方重复使用该算法。对于您的情况,您的算法基本上是这样的:
- 对于列表中的每个元素
- 对该元素执行操作x
- 返回新列表
关键是能够根据需要传入新的操作来替换“x”。在函数式编程世界中,我们创建一个称为“functor”的对象,它实际上只是一种将函数封装在对象中的方法。(如果Java有闭包,这将更容易,但这就是我们所拥有的。)
无论如何,这里有一些代码可以实现您想要的功能:
类:Inverse
import com.google.common.base.Function;
public class Inverse implements Function
{
@Override
public Double apply(Double arg0)
{
return Math.pow(arg0, -1);
}
}
类:对数
import com.google.common.base.Function;
public class Logarithm implements Function
{
@Override
public Double apply(Double arg0)
{
return Math.log(arg0);
}
}
类:驱动程序
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Collections2;
public class Driver
{
@Test
public void testInverse()
{
List initialValues = Arrays.asList(new Double[] {1.0, 2.0, 3.0});
List logValues = new ArrayList(Collections2.transform(initialValues, new Inverse()));
assertEquals(3, logValues.size());
assertEquals(Double.valueOf(1.0), logValues.get(0), 0.01);
assertEquals(Double.valueOf(0.5), logValues.get(1), 0.01);
assertEquals(Double.valueOf(0.333), logValues.get(2), 0.01);
}
}
Driver类只包含一个测试用例,但它确实说明了上面定义的Functors的使用方法。您会注意到在上面的testInverse方法中使用了一个名为Collections2.transform的方法。您可以在此处找到有关此方法的文档:
http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Collections2.html#transform%28java.util.Collection,%20com.google.common.base.Function%29
本质上,这种方法抽象了遍历列表并对每个元素应用某些函数的算法 - 你所要做的就是应用该函数来执行。因此,在这种情况下,我向该方法传递一组Double和一个函数对象(Inverse)。它会给我返回一个包含初始列表中每个值的倒数的新列表。如果您希望执行每个值的对数,则可以将不同的函数对象传递给transform方法。
这种类型的编程确实需要一点学习曲线,但对于您想要重复使用代码的类型来说绝对是很棒的。通过利用现有的库(如Guava),您甚至可以使自己的代码更容易编写。注意,我编写的代码实际上比您写的代码更容易,因为在执行我的数学函数时,我不必处理列表/数组 - 我只需对一个元素执行该函数;transform函数负责将该函数应用于整个列表。