我正在编写一个程序来计算一个值,该值是两个对象之间相似性的度量。比较是可交换的,so compare(a, b) == compare(b, a)
。
程序输出到控制台是所有结果的矩阵。但是,由于矩阵每次比较两次((a, b)
和(b, a)
),我只想通过计算一次来节省时间。缓存这些结果的最佳方法是什么?
输出结果的粗略示例:
a b c
a 0 20 9001
b 20 0 333
c 9001 333 0
答案 0 :(得分:3)
听起来你已经真正地缓存了结果 - 在矩阵中。只需计算矩阵的一个“三角形”,然后填写其余部分:
// Compute one triangle
for (int i=0; i < size; i++)
{
for (int j=0; j <= i; j++)
{
matrix[i][j] = computeValue(i, j);
}
}
// Now mirror it
for (int i = 0; i < size; i++)
{
for (int j = i + 1; j < size; j++)
{
matrix[i][j] = matrix[j][i];
}
}
答案 1 :(得分:2)
正如其他人所提到的,你应该只计算三角形的一边。 你不是要复制它,甚至也不为它分配空间。只需将你的x和y坐标转换成一个索引,你就可以得到一个比一半大一点的数组。全方矩阵。例如:
class SymmetricMatrix {
private final double[];
/**
* @param size the size of one dimension of the matrix. eg: 3 for a 3x3 matrix.
*/
SymmetricMatrix(int size) {
matrix = new double[index(size) + 1];
}
private index(int x, int y) {
if (x > y) {
int tmp = x;
x = y;
y = tmp;
}
// now x <= y
i = (y * y + y) / 2 + x;
}
public double get(int x, int y) {
return matrix[index(x, y)];
}
public void set(int x, int y, double value) {
matrix[index(x, y)] = value;
}
}
此示例使用双值,但您可以轻松地调整它(如果您想使用对象,甚至可以使其成为通用值)。
填写:
SymmetricMatrix matrix = new SymmetricMatrix(size);
for (int y = 0; y < size; y++) {
for (int x = 0; x <= y; x++) {
matrix.set(x, y, /* value */);
}
}
答案 2 :(得分:0)
仅计算一个三角形,并创建类似
的访问函数get(int x, int y) {
if (x > y) { return matrix[x][y] };
return matrix[y][x];
答案 3 :(得分:0)
看起来你不需要这个任务但是如果你有一个昂贵的功能并且需要缓存结果,那么这里有一个非常好的线程安全方法:
答案 4 :(得分:0)
您需要非常小心缓存compareTo
和equals
等方法的结果。
如果您有N个数组实例,则可能需要缓存N ^ 2个比较结果。 (这当然取决于应用......)
此外,如果您的应用程序创建并丢弃大量(矩阵)实例,则最终可能会在缓存中出现大量条目,从而导致垃圾保留问题。您可以使用弱引用缓解此问题,但它们会使垃圾收集速度明显变慢。
如果我这样做,我首先会分析应用程序,以确定compareTo
和equals
方法是否真的存在瓶颈。如果它们是,我会考虑使用除缓存之外的其他东西来加速方法;例如为每个数组存储一个延迟计算的哈希可以加快equals
。