Java 中的记忆化
好吧,在 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;
}
}
}
这可以用来获得明显的收益:
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);
}
}
我确信它可以变得更加通用和优雅。 我知道如果 x>20 就会出现溢出异常。 (而且我也可能有类型转换错误) 但希望我表达了我的观点:我可以创建一个类,可以满足纯数学函数(即确定性、无副作用函数)记忆的需求 并获得惊人的性能提升。
我怎样才能在Java中完成类似的事情?
Ok so in C# I could write:
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;
}
}
}
Which could be made use of for obvious gains:
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);
}
}
I'm sure it could be made more general and elegant.
And I know I'll have overflow exceptions if x>20.
(And I may have typecast errors in there too)
BUt hopefully I made my point: i can create a class that can furful the needs for memoisation of pure mathematical functions (I.e. deterministic, side-effect free functions)
and get wonderful performance gains.
How can I accomplish a similar thing in Java?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在Java 8中,您可以使用computeIfAbsent来实现记忆化:
}
结果是:
更多详细信息请参见http://rdafbn.blogspot.ie/2015/06/memoize-functions-in-java-8.html
最后,您可以使用 cyclops 库删除创建 memoize 泛型方法的样板代码(看看http://static.javadoc.io/com.aol.cyclops/cyclops-functions/4.0.2/com/aol/cyclops/functions/Memoise.html)
In Java 8 you can use the computeIfAbsent to achieve memoization :
}
Result is :
More details here http://rdafbn.blogspot.ie/2015/06/memoize-functions-in-java-8.html
Lastly, you can use the cyclops library to remove the boilerplate code of creating memoize generic methods( have a look at http://static.javadoc.io/com.aol.cyclops/cyclops-functions/4.0.2/com/aol/cyclops/functions/Memoise.html)
java 中不能将函数作为数据类型传递。要解决此问题,请使用接口。
现在您可以将innerFactorial 设置为数据类型。
这允许您将
innerFactorial
作为数据类型传递:并调用您编写的函数:
另外,在 Java 中不要将字段或方法名称大写。它不是标准的,并且使代码更难阅读。
You can't pass functions as data types in java. To fix this, use an interface.
Now you can set innerFactorial to a data type.
This lets you pass
innerFactorial
as a data type:And to call the function you write this:
Also, in Java don't capitalize field or method names. It's not standard and makes the code harder to read.
查看 Guava 的 缓存包。这就是它的用途。
Check out Guava's cache package. This is what it is for.
您无法在 Java 中从
创建泛型映射,因为泛型类型参数仅绑定到引用类型。您必须将其设为
,这涉及包装原语,并且可能会给您的记忆带来一些开销。除此之外,Java 的翻译非常简单。请注意,您只能记住提供有用的 equals 和 hashCode 实现的类型,并且需要使用大小有限制的、线程安全的弱键表例如 MapMaker。
You can't create a generic map from
<short, ulong>
in Java because generic type parameters only bind to reference types. You would have to make it<Short, Long>
which involves wrapping primitives and may introduce some overhead into your memoization.Besides that, the translation to Java is pretty straight-forward. Just be aware, you can only memoize types that provide a useful
equals
andhashCode
implementations, and you need to use a size-bounded, thread-safe, weak-key table such as that provided by MapMaker.