Java 如何将搜索友好号码的实现从命令式转变为功能性?

Java 如何将搜索友好号码的实现从命令式转变为功能性?,java,functional-programming,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 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;
}
我看不到任何状态或副作用可以减少。
在这个实现中还应该做些什么来满足FP范式?

如果(isAmicable(p,o))和使用
System.out.println(p+“”+o)进行forEach之后,使用filter或带有形成消息和afrer
System.out.println的map

这里有一个替代方案,可以生成所有友好对的
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));
映射对=
IntStream.range(11000)
.boxed()
.flatMap(p->IntStream.range(p+11000)
.filter(o->isAmicable(p,o))
.mapToObj(o->newsimplentry(p,o)))
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));

当然,就性能而言,这是相当糟糕的,因为您对同一个
i
计算了多次
sumpropertivisiors(i)
。为每个
i
计算一次
sumpropertivisiors(i)
,将结果存储在
Map
中,并检查哪些
i
j
对满足
sumpropertivisiors(i)==j和&sumpropertivisiors(j)==i
,这是个好主意,但随后声明一个新变量。这个映射对可以被另一个纯函数替换吗?@pobu它是一个纯函数,有一个返回值。你必须以某种方式归还友好的一对。你会用什么来代替地图?如果将
search()
的返回类型从void更改为
Map
,则可以消除该变量。然后,您只需返回流管道的结果。解决方案中有一个自动装箱(int->Integer),它可以真正提高性能bad@pobu您是运行了基准测试,还是只是假设性能会很差?我用System.currentTimeMillis()做了一个非常简单的基准测试。以下是结果:search()-6002秒;流();和对()-9918秒。我应该重复几次来验证结果。
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));