如何构建更高效的功能代码?Java FP
当我在学习Euler项目时,我几乎找不到用函数方法解决问题的方法 目标是找到一个可以被2到20之间的所有整数整除的数 我首先用经典Java解决了这个问题(我知道我的代码不是很好,对此我很抱歉),然后我想用FP获得结果,认为效率会更高 普通旧java花了750毫秒才找到结果。 流/FP大约耗时750毫秒。 关于为什么FP way需要这么多时间来完成,您有什么想法/解释吗? 我想我的代码不是更好的,既不是普通的java代码,也不是FP代码 但我想知道我哪里出了问题 请注意,并行流处理将获得大约130毫秒(750毫秒->620毫秒) 注意2:最好从如何构建更高效的功能代码?Java FP,java,functional-programming,Java,Functional Programming,当我在学习Euler项目时,我几乎找不到用函数方法解决问题的方法 目标是找到一个可以被2到20之间的所有整数整除的数 我首先用经典Java解决了这个问题(我知道我的代码不是很好,对此我很抱歉),然后我想用FP获得结果,认为效率会更高 普通旧java花了750毫秒才找到结果。 流/FP大约耗时750毫秒。 关于为什么FP way需要这么多时间来完成,您有什么想法/解释吗? 我想我的代码不是更好的,既不是普通的java代码,也不是FP代码 但我想知道我哪里出了问题 请注意,并行流处理将获得大约130
9699690L
开始(也就是说:2*3*5*7*9*11*13*17*19
),但对于应用程序(普通的旧Java和FP方式)来说,启动起来似乎非常漫长。。。为什么
下面是简单的旧Java代码:
@Test
void test() {
long start = System.currentTimeMillis();
boolean foundValue = false;
long valueToFindOut = 20L;
List<Long> divisors = Arrays.asList(2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L,
19L, 20L);
while (!foundValue) {
boolean found = false;
for (long div : divisors) {
if (isDivisible(valueToFindOut, div)) {
found = true;
} else {
found = false;
break;
}
}
if (!found) {
valueToFindOut += 20L;
} else {
foundValue = true;
System.out.println("Valeur trouvée = " + valueToFindOut);
}
}
for (long div : divisors) {
assertTrue(isDivisible(valueToFindOut, div));
}
long end = System.currentTimeMillis();
System.out.println("Résultat obtenu en " + (end - start) + " millisecondes");
}
private boolean isDivisible(long toDivide, long divisor) {
return toDivide % divisor == 0;
}
@测试
无效测试(){
长启动=System.currentTimeMillis();
布尔值=false;
长值ToFinOut=20L;
列表除数=数组。asList(2L、3L、4L、5L、6L、7L、8L、9L、10L、11L、12L、13L、14L、15L、16L、17L、18L、,
19L、20L);
而(!foundValue){
布尔值=false;
for(长除数:除数){
if(可分割(输入值,div)){
发现=真;
}否则{
发现=错误;
打破
}
}
如果(!找到){
输入值+=20L;
}否则{
foundValue=true;
System.out.println(“Valeur trouvée=“+valuetofinout”);
}
}
for(长除数:除数){
资产真实(可分割(ValueToFinout,div));
}
long end=System.currentTimeMillis();
System.out.println(“Résultat obtenus en”+(结束-开始)+“毫秒”);
}
私有布尔可分(长toDivide,长除数){
返回divide%除数==0;
}
功能代码如下所示:
@Test
void testLambda() {
long start = System.currentTimeMillis();
List<Long> divisors = Arrays.asList(2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L,
19L, 20L);
Predicate<Long> predicate = longPredicate(divisors);
long result = generateLongStream().filter(predicate).findFirst().get();
long end = System.currentTimeMillis();
System.out.println("Resultat = " + result + " obtenu en " + (end - start) + " millisecondes.");
}
private boolean isDivisible(long toDivide, long divisor) {
return toDivide % divisor == 0;
}
private Stream<Long> generateLongStream() {
return Stream.iterate(20L, l -> l + 20L).parallel();
}
private Predicate<Long> longPredicate(List<Long> longs) {
long start = System.currentTimeMillis();
Predicate<Long> predicate = null;
if(!(longs.isEmpty())) {
List<Predicate<Long>> predicates = new ArrayList<Predicate<Long>>(longs.size());
longs.forEach(divisor -> {
predicates.add(valueToTest -> isDivisible(valueToTest, divisor));
});
for(int i = 0; i < predicates.size(); i++) {
if(i == 0) {
predicate = predicates.get(i);
} else {
predicate = predicate.and(predicates.get(i));
}
}
}
long end = System.currentTimeMillis();
System.out.println("Predicate construit en " + (end - start) + " millisecondes.");
return predicate;
}
@测试
void testLambda(){
长启动=System.currentTimeMillis();
列表除数=数组。asList(2L、3L、4L、5L、6L、7L、8L、9L、10L、11L、12L、13L、14L、15L、16L、17L、18L、,
19L、20L);
谓词=长谓词(除数);
长结果=generateLongStream().filter(谓词).findFirst().get();
long end=System.currentTimeMillis();
System.out.println(“Resultat=“+result+”obtenus en“+(结束-开始)+”毫秒”);
}
私有布尔可分(长toDivide,长除数){
返回divide%除数==0;
}
私有流生成器LongStream(){
return Stream.iterate(20L,l->l+20L).parallel();
}
专用谓词longPredicate(列表long){
长启动=System.currentTimeMillis();
谓词=null;
if(!(longs.isEmpty()){
列表谓词=新的ArrayList(longs.size());
longs.forEach(除数->{
add(valueToTest->isDivisible(valueToTest,除数));
});
for(int i=0;i
谢谢你的建议。我们可以代替在一个列表上循环
for( Thing thing : things ){
process(thing);
}
…有更实用的东西
things.forEach( thing -> process( thing ) );
…但实际发生的情况非常相似:我们必须对列表中的每个元素迭代调用过程
方法。函数版本甚至可能稍微慢一点,因为在调用有用的方法之前,有一个额外的方法调用lambda
因此,我认为功能版本与原始版本花费的时间相似并不奇怪
功能版本的优点可能是
- 稍微短一点
- 你可能会发现它更容易阅读
- lambda可以从其他地方提供(例如作为一种方法) 参数)
- lambda需要的样板代码比匿名内部类少得多
但是这些都不会有助于提高性能。我们可以取代在列表上循环
for( Thing thing : things ){
process(thing);
}
…有更实用的东西
things.forEach( thing -> process( thing ) );
…但实际发生的情况非常相似:我们必须对列表中的每个元素迭代调用过程
方法。函数版本甚至可能稍微慢一点,因为在调用有用的方法之前,有一个额外的方法调用lambda
因此,我认为功能版本与原始版本花费的时间相似并不奇怪
功能版本的优点可能是
- 稍微短一点
- 你可能会发现它更容易阅读
- lambda可以从其他地方提供(例如作为一种方法) 参数)
- lambda需要的样板代码比匿名内部类少得多
但是这些都不会有助于提高性能。我首先要回答我的评论:在处理基于
长的算法时,应该避免长,而偏爱Long
你决不能忽视(取消)装箱操作的成本:我使用long
,long[]
,重写了你的代码