稀疏矩阵指的是矩阵中绝大多数元素为同一默认值,仅少量元素为有效非默认值的特殊矩阵结构,在图计算、推荐系统、数值分析等场景中有广泛应用。处理稀疏集合时,如何高效存储这类矩阵的非默认元素,是提升空间利用率的核心问题。

常规二维数组存储的局限性
最直观的存储方式是使用二维数组,为每个矩阵位置分配固定空间,不管该位置是否为有效元素。假设我们有一个1000*1000的稀疏矩阵,其中仅1000个元素为非默认值,其余都是0,用二维数组存储的实现如下:
// 定义1000*1000的稀疏矩阵,默认值为0 int[][] sparseMatrix = new int[1000][1000]; // 仅设置少量有效元素 sparseMatrix[12][34] = 5; sparseMatrix[78][90] = 12; sparseMatrix[234][567] = 8; // 其余999000个位置都存储默认的0,浪费大量空间
这种方式的缺点是空间利用率极低,每个int类型元素占4字节,整个矩阵需要占用1000*1000*4=4MB空间,而实际有效数据仅占用1000*4=4KB空间,空间浪费超过99%。
使用Map存储稀疏矩阵的实现
Map的键值对结构可以只存储非默认的有效元素,键用来表示元素的位置,值用来表示元素的内容,避免存储大量默认值。我们可以用坐标拼接或者自定义对象作为键,实现如下:
import java.util.HashMap;
import java.util.Map;
public class SparseMatrixMapStorage {
// 用字符串拼接坐标作为键,值为元素内容,默认值为0不存储
private Map<String, Integer> matrixMap = new HashMap<>();
private int row;
private int col;
public SparseMatrixMapStorage(int row, int col) {
this.row = row;
this.col = col;
}
// 设置矩阵元素
public void setElement(int r, int c, int value) {
if (r < 0 || r >= row || c < 0 || c >= col) {
throw new IllegalArgumentException("坐标超出矩阵范围");
}
if (value == 0) {
// 默认值为0,从Map中移除该键,避免存储无效数据
matrixMap.remove(r + "," + c);
} else {
matrixMap.put(r + "," + c, value);
}
}
// 获取矩阵元素
public int getElement(int r, int c) {
if (r < 0 || r >= row || c < 0 || c >= col) {
throw new IllegalArgumentException("坐标超出矩阵范围");
}
return matrixMap.getOrDefault(r + "," + c, 0);
}
// 获取存储的有效元素数量
public int getValidElementCount() {
return matrixMap.size();
}
}
两种存储方式的空间利用率对比
我们可以通过具体数据对比两种方案的空间占用:
| 矩阵规模 | 有效元素数量 | 二维数组占用空间 | Map存储占用空间(估算) | 空间利用率提升比例 |
|---|---|---|---|---|
| 1000*1000 | 1000 | 4MB | 约16KB(键+值+Map开销) | 约99.6% |
| 5000*5000 | 5000 | 100MB | 约80KB | 约99.92% |
| 10000*10000 | 10000 | 400MB | 约160KB | 约99.96% |
可以看到,随着矩阵规模增大,有效元素占比越低,Map存储的空间优势越明显。Map存储仅需要为有效元素分配空间,大幅减少了默认值的存储开销。
Map存储的适用场景与注意事项
Map存储稀疏矩阵虽然空间利用率高,但也有适用边界:
- 适合有效元素占比低于10%的稀疏矩阵场景,空间收益明显
- 有效元素占比过高时,Map的键值对额外开销可能超过二维数组的存储成本,此时不建议使用
- 如果频繁需要遍历矩阵所有元素,Map的遍历效率低于二维数组,需要结合业务场景权衡
另外,键的设计也会影响空间占用,除了字符串拼接坐标,也可以使用自定义对象作为键,重写hashCode和equals方法,减少键的存储开销。如果是数值类型的矩阵,还可以用Integer的复合键,进一步提升存储效率。
总结
在稀疏集合的处理中,使用Map存储稀疏矩阵变量,能够大幅减少默认值的存储开销,显著提升空间利用率,尤其适合大规模、低有效元素占比的稀疏矩阵场景。开发者需要根据实际的有效元素占比、访问频率等需求,选择最合适的存储方案,平衡空间效率和访问性能。