C# Java中的记忆

C# Java中的记忆,c#,java,performance,function,memoization,C#,Java,Performance,Function,Memoization,好的,我可以用C写: public class Memorizer<K,TRes> { private Dictionary<K,TRes> _mem; private Func<K,TRes> _function public Memorizer (Func<K,TRes> function) { _function = function; _mem= new Dictionary

好的,我可以用C写:

public class Memorizer<K,TRes>
{
    private Dictionary<K,TRes> _mem;
    private Func<K,TRes> _function

    public Memorizer (Func<K,TRes> function)
    {
        _function = function;
        _mem= new Dictionary<K,TRes>();
    }

    public TRes Call(K arg)
    {
        if (mem.ContainsKey(arg)
        {
            return _mem[arg];
        }
        else
        {
            TRes ret=_function(arg);
            _mem[arg] = ret;
            return ret;
        }
    }
}
公共类存储器
{
私人词典;
私有函数
公共存储器(Func函数)
{
_功能=功能;
_mem=新字典();
}
公共TRes呼叫(K arg)
{
if(成员ContainsKey(arg)
{
返回_mem[arg];
}
其他的
{
TRes ret=_函数(arg);
_mem[arg]=ret;
返回ret;
}
}
}
可以利用这些资源获得明显的收益:

public class FactorialCalculator()
{
    private Memorizer<ushort, ulong> _memorizedFactorial;
    public FactorialCalculator()
    {
        _memorizedFactorial = new Memorizer<ushort, ulong> (innerFactorial);
    }

    private ulong innerFactorial(ushort x)
    {
        return (x=0) ? 1 : x*Factorial(x-1)
    }

    public ulong factorial(ushort x)
    {
        _memorizedFactorial.Call(x);
    }

}
public类factoriacalculator()
{
私有存储器_memberedfactorial;
公因子计算器()
{
_记忆因子=新的记忆因子(内因子);
}
私有ulong内因子(ushort x)
{
收益率(x=0)?1:x*阶乘(x-1)
}
公共ulong阶乘(ushort x)
{
_记忆阶乘调用(x);
}
}
我相信它可以变得更一般、更优雅。 我知道如果x>20,我会有溢出异常。 (我可能也有打字错误) 但我希望我能表达我的观点:我可以创建一个类,满足纯数学函数(即确定性、无副作用函数)的记忆需求 并获得出色的性能增益


我怎样才能在Java中完成类似的事情呢?

请查看Guava的包。这就是它的用途。

您不能从Java中的
创建泛型映射,因为泛型类型参数只绑定到引用类型。您必须将其设置为
,这涉及到包装原语,可能会给您带来一些开销回忆录


除此之外,到Java的转换非常简单。请注意,您只能记忆提供有用的
equals
hashCode
实现的类型,并且您需要使用大小有界、线程安全、弱键表,如提供的。

您不能在Java中将函数作为数据类型传递。要修复这需要使用一个接口

public interface ReturnFunction<K, V> {
    public V getValue(K k);
}
要调用函数,请编写以下代码:

long someLong = _memoizedFactorial.getValue(someShort);

此外,在Java中,字段或方法名称不能大写。这不是标准名称,使代码更难阅读。

在Java 8中,您可以使用ComputeFabSent来实现记忆:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

public class FactorialCalculator {

public static void main(String[] args) {

    Function<Integer, Long> factorialFunction = x -> {
        System.out.println("Calculating factorial for " + x);
        long fact = 1;
        for (int i = 1; i <= x; i++) {
            fact *= i;
        }
        return fact;
    };

    Function<Integer, Long> memoziedFactorialFunction = memoise(factorialFunction);

    System.out.println(memoziedFactorialFunction.apply(5));
    System.out.println(memoziedFactorialFunction.apply(5));
    System.out.println(memoziedFactorialFunction.apply(5));
    System.out.println(memoziedFactorialFunction.apply(5));
    System.out.println(memoziedFactorialFunction.apply(6));
    System.out.println(memoziedFactorialFunction.apply(6));

}

public static <X, Y> Function<X, Y> memoise(Function<X, Y> fn) {
    Map<X, Y> pp = new ConcurrentHashMap<X, Y>();
    return (a) -> pp.computeIfAbsent(a, fn);
}
这里有更多细节


最后,您可以使用该库删除创建memoize泛型方法的样板代码(请查看)

我相信这些方法被称为“memoizer”,而不是“memory”。此外,它是字典,而不是“new Dictionary”中的Dictionary另外,基于素数分解计算阶乘更有效。对于每个素数p@Mike,这只是一个示例。为了演示一个点。酷,C#的Func类型的Java等价物是什么?唯一的额外思想变化是
函数
。Java没有符合上述语法的真正函数。您需要证明ide一个给定一种类型的接口返回另一种类型。Guava有这样一个:函数-检查Guava的函数接口。不需要重新发明轮子。@John B Thanx以前从未听说过它,但它很好。出于理论目的,并且因为不赞成为3行代码引入额外的libnray。重新发明轮子没有错轮子。如果我想在一个类中记忆多个函数呢?我必须将每个函数都封装在一个内部类中实现函数吗?或者有更优雅的方式吗?
,因为不赞成为3行代码引入额外的libnray。重新发明轮子没有错。
我不能再反对了。memorizatio如果编译器或运行时能够为我们做到这一点,n将是一件伟大的事情。如果编译器/运行时能够安全地假设零副作用方法,这将是一个现实,不是吗?请参阅
long someLong = _memoizedFactorial.getValue(someShort);
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

public class FactorialCalculator {

public static void main(String[] args) {

    Function<Integer, Long> factorialFunction = x -> {
        System.out.println("Calculating factorial for " + x);
        long fact = 1;
        for (int i = 1; i <= x; i++) {
            fact *= i;
        }
        return fact;
    };

    Function<Integer, Long> memoziedFactorialFunction = memoise(factorialFunction);

    System.out.println(memoziedFactorialFunction.apply(5));
    System.out.println(memoziedFactorialFunction.apply(5));
    System.out.println(memoziedFactorialFunction.apply(5));
    System.out.println(memoziedFactorialFunction.apply(5));
    System.out.println(memoziedFactorialFunction.apply(6));
    System.out.println(memoziedFactorialFunction.apply(6));

}

public static <X, Y> Function<X, Y> memoise(Function<X, Y> fn) {
    Map<X, Y> pp = new ConcurrentHashMap<X, Y>();
    return (a) -> pp.computeIfAbsent(a, fn);
}
Calculating factorial for 5
120
120
120
120
Calculating factorial for 6
720
720