
本文介绍在 ojAlgo 库中对 Primitive64Matrix(新版为 MatrixR064)或可变矩阵 Primitive64Store 的每一行进行原地或高效排序的正确实践,避免低效复制,并提供清晰、高性能的代码示例。
本文介绍在 ojalgo 库中对 `primitive64matrix`(新版为 `matrixr064`)或可变矩阵 `primitive64store` 的每一行进行原地或高效排序的正确实践,避免低效复制,并提供清晰、高性能的代码示例。
在使用 ojAlgo 进行数值计算时,一个常见需求是对矩阵的每一行独立排序(例如按升序排列)。但需特别注意:Primitive64Matrix(在 ojAlgo v50+ 中已重命名为 MatrixR064)是不可变(immutable)类型——任何“修改”操作(如替换某一行)都必须通过 copy() 创建新实例,这会带来额外开销。而 Primitive64Store(对应 MatrixStore<Double> 的原始存储实现)则是可变(mutable)类型,支持直接写入,是更优的选择。
✅ 推荐方案:使用 Primitive64Store 实现高效行排序(无拷贝)
Primitive64Store 允许直接调用 fillRow() 修改指定行,无需创建中间副本,显著提升性能与可读性:
import org.ojalgo.matrix.store.Primitive64Store;
import org.ojalgo.matrix.store.MatrixStore;
import org.ojalgo.structure.RowView;
import org.ojalgo.array.ArrayR064;
import java.util.Arrays;
double[][] tab = { { 1, 3, 4, 2 }, { 0, 4, 3, 1 } };
Primitive64Store matrix = Primitive64Store.FACTORY.rows(tab); // 可变存储
// 预分配临时数组,复用内存(避免循环内重复 new)
ArrayR064 temp = ArrayR064.make(matrix.getColDim());
for (RowView<Double> rowView : matrix.rows()) {
rowView.supplyTo(temp.data); // 将当前行数据提取到 temp.data
Arrays.sort(temp.data); // 对一维数组原地排序
matrix.fillRow(rowView.row(), temp); // 直接写回该行(in-place)
}
// 此时 matrix 已被就地修改,每行均已升序排列
System.out.println(matrix);
// 输出:
// [0, 1, 3, 4]
// [1, 2, 3, 4]? 关键优势:
- 零矩阵拷贝(matrix.copy() 完全省略);
- 复用 ArrayR064 缓冲区,避免频繁内存分配;
- 利用 RowView 的 supplyTo() 和 fillRow() 实现高效数据搬运。
⚠️ 若必须使用 MatrixR064(旧版 Primitive64Matrix)
由于其不可变性,只能通过 DenseReceiver 构建新矩阵。此时应复用 receiver 并最小化中间对象:
MatrixR064 matrix = MatrixR064.FACTORY.rows(tab);
DenseReceiver receiver = matrix.copy(); // 仅初始化一次
ArrayR064 temp = ArrayR064.make(matrix.getColDim());
for (RowView<Double> rowView : matrix.rows()) {
rowView.supplyTo(temp.data);
Arrays.sort(temp.data);
receiver.fillRow(rowView.row(), temp); // 向 receiver 写入
}
matrix = receiver.get(); // 最终一次性获取新矩阵⚠️ 注意:此处 receiver 是可累积写入的,不应在循环内反复调用 matrix.copy()(如原始代码所示),否则每次都会复制整个矩阵,时间复杂度退化为 O(m²n)。
? 总结与最佳实践
- 优先选用 Primitive64Store:当需要频繁修改矩阵内容(如逐行排序、归一化等)时,它是性能与语义更匹配的选择;
- 避免滥用不可变类型做“伪修改”:MatrixR064 适合构建后只读场景(如传递给算法函数),而非迭代更新;
- 始终复用临时缓冲区:ArrayR064.make(cols) 创建一次即可,在循环中重用 .data 字段;
- 理解 RowView 的作用:它提供对某行逻辑视图的只读访问,配合 supplyTo() 和 fillRow() 实现高效数据流;
- 版本兼容提示:若使用 ojAlgo ≥ v50,请将 Primitive64Matrix 替换为 MatrixR064,并导入 org.ojalgo.matrix.MatrixR064。
掌握这些模式,你就能在保持代码简洁的同时,充分发挥 ojAlgo 在高性能数值计算中的设计优势。

















