如何将搜索友好数字的实现从命令式转换为功能式?

时间:2019-06-05 09:35:06

标签: java functional-programming

我有一个简单的命令式实现算法来搜索友好数字。现在,我尝试使其更具功能性。

public static void search(){

    for(int i = 1; i < 10000; i++){
        for(int j = i+1; j < 10000; j++){
            if(isAmicable(i, j)){
                System.out.println(i + " " + j);
            }
        }
    }
}

public static boolean isAmicable(int i, int j){
    return sumProperDivisors(i) == j && sumProperDivisors(j) == i;
}

public static int sumProperDivisors(int num){
    int result = 0;
    for(int i = 1; i < num; i++){
        if(num%i == 0) result +=i;
    }
    return result;
}

首先,我在search()方法中将循环替换为IntStreams。

public static void streamed(){
    IntStream.range(1, 10000).forEach(p -> {    
        IntStream.range(p+1, 10000).forEach(o -> {
            if(isAmicable(p, o)) System.out.println(p + " " + o);
        });
    });
}

我认为任何状态或副作用都不会减少。 此实现中还应该做些什么来满足FP范例?

2 个答案:

答案 0 :(得分:1)

使用过滤器代替if(isAmicable(p, o)),在forEach之后使用System.out.println(p + " " + o);或使用形成消息并在System.out.println之后进行映射

答案 1 :(得分:1)

以下是一种产生所有友好对的Map而不产生副作用的替代方法:

Map<Integer,Integer> pairs =
    IntStream.range(1, 10000)
             .boxed()
             .flatMap(p -> IntStream.range(p+1, 10000)
                                    .filter(o -> isAmicable(p, o))
                                    .mapToObj(o -> new SimpleEntry<>(p,o)))
             .collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));

当然,就性能而言,这是非常糟糕的,因为您为同一sumProperDivisors(i)计算了i次。为每个sumProperDivisors(i)计算一次i,将结果存储在Map中,并检查ij的哪些对满足{ {1}}。