【问题标题】:Filter TreeMap with integer array key and perform arithmetic operations使用整数数组键过滤 TreeMap 并执行算术运算
【发布时间】:2015-04-19 13:33:40
【问题描述】:

我用 Java 编写了一个复杂的程序,我需要管理许多包含整数值的大型稀疏矩阵。 示例:

int A[][][][];
int B[][][];
int C[][];

为了节省内存、空间等,我决定将这些数据存储在 TreeMap 中。我知道存在很多做得更好的库,但我会尝试实施我的个人解决方案。 首先,我创建了一个类 Index 来标识这个数组的索引而不知道它们有多少。

public class Index implements Comparable<Index> {
    private final int[] index;

    public Index(int ... index) {
        this.index = index;
    }

    @Override
    public int toCompare(Index i) {
        ...
    }
}

显然我已经使用这个类以这种方式定义我的三个地图:

Map <Index, Integer> mapA = new TreeMap <> ();
Map <Index, Integer> mapB = new TreeMap <> ();
Map <Index, Integer> mapC = new ...

现在,我需要将之前创建的矩阵中的数据存储到这些地图中。最简单的方法是使用 4/3/2/.. 循环,但我很乐意接受其他解决方案。

for(int s = 0; s < s_max; s++) {
            for(int c = 0; c < c_max; c++) {
                for(int o = 0; o < o_max; o++) {
                    for(int d = 0; d < d_max; d++) {
                        mapA.put(new Index(s,c,o,d), A[s][c][o][d]);
                    }
                }
            }
        }

问题的重点是我需要检索数据的时候,但让我解释一下。这些映射之间更常见的操作是将它们视为矩阵或数组的乘法和加法。每次我需要执行如下操作时,我都无法创建 6(..) 个嵌套循环(我无法插入图像,因为我的声誉仍然很低):

http://postimg.org/image/7m8v0kiwn/

我的问题是:

  1. 如何从键中过滤我的值?
  2. 有办法(可能使用 lambda 表达式)来执行这种类型的操作吗?
  3. 关于这个问题有什么建议吗?

【问题讨论】:

  • 为什么您认为将数组复制到 TreeMap 会节省内存?此外,使用数组作为映射的键没有意义,因为数组是使用不覆盖等号和哈希码的动态类创建的,因此除非您具有对原始数组的引用,否则您无法在映射中找到某些东西是用作键。
  • 你需要更清楚你的问题,你当前的解决方案,你为什么要这样做,以及你当前的解决方案有什么问题。
  • @bot 数组是稀疏的,所以使用不同的结构可以节省内存。
  • 我选择了 TreeMap 而不是 HashMap,因为我读到第二个在计算巨大数组中的哈希方面更昂贵。您可以在下面找到的文章讨论了 Trie(而不是 HashMap),我认为树状结构可能比哈希状结构更好。
    来自:stackoverflow.com/questions/390181/…

标签: java dictionary lambda java-8 sparse-matrix


【解决方案1】:

请注意,您不需要创建Index 类;你需要的类型already exists

来自IntBuffer.compareTo的文档:

两个 int 缓冲区通过按字典顺序比较剩余元素的序列来进行比较,而不考虑每个序列在其相应缓冲区中的起始位置。

因此,如果您 wrap 整数数组保存索引并将位置和限制保持在默认值,缓冲区将提供所需的行为。


以一般方式执行数组到映射转换是可行的,如果考虑到在 Java 中,每个多维数组也是Object[] 的一个实例,而不管它们的基本类型如何。即,int[][] 类型是 Object[] 的子类型,其元素是 int[] 的实例,Object 的子类型。此外,Object[][]Object[] 的子类型,其元素的类型为Object[]Object 的子类型。

因此,您可以使用与 Object[] 相同的方式处理所有维度来遍历它,并且只需要关心 last 维度的实际类型,对于任何 n-维int数组:

/** accepts all int arrays from one to 255 dimensions */
public static TreeMap<IntBuffer,Integer> toMap(Object array) {
    int dim=1;
    for(Class<?> cl=array.getClass(); ; cl=cl.getComponentType())
        if(Object[].class.isAssignableFrom(cl)) dim++;
        else if(cl==int[].class) break;
        else throw new IllegalArgumentException(array.getClass().getSimpleName());
    TreeMap<IntBuffer,Integer> map=new TreeMap<>();
    fill(map, new int[dim], 0, array);
    return map;
}

private static void fill(TreeMap<IntBuffer, Integer> map, int[] i, int ix, Object array) {
    int next=ix+1;
    i[ix]=0;
    if(next<i.length)
        for(Object part: (Object[])array) {
            if(part!=null) fill(map, i, next, part);
            i[ix]++;
        }
    else
        for(int val: (int[])array) {
            if(val!=0) map.put(IntBuffer.wrap(i.clone()), val);
            i[ix]++;
        }
}

此解决方案以递归方式处理维度,但原则上可以采用非递归方式。但是递归深度自然受限于数组/矩阵的维数。

它只会将非零值放入映射中,并且还会跳过任何null 子数组,因此它不介意数组表示是否已经稀疏。

示例用法可能如下所示

int[][][][] array=new int[5][5][5][5];
array[1][2][3][4]=42;
array[4][3][2][1]=1234;
TreeMap<IntBuffer, Integer> sparse=toMap(array);
sparse.forEach((index,value)-> {
    for(int ix:index.array()) System.out.print("["+ix+']');
    System.out.println("="+value);
});

将打印:

[1][2][3][4]=42
[4][3][2][1]=1234

另一个例子:

int[][] id = {
  {1},
  {0, 1},
  {0, 0, 1},
  {0, 0, 0, 1},
  {0, 0, 0, 0, 1},
  {0, 0, 0, 0, 0, 1},
  {0, 0, 0, 0, 0, 0, 1},
};
TreeMap<IntBuffer, Integer> idAsMap = toMap(id);
System.out.println(idAsMap.size()+" non-zero values");
idAsMap.forEach((index,value)-> {
    for(int ix:index.array()) System.out.print("["+ix+']');
    System.out.println("="+value);
});

将打印:

7 non-zero values
[0][0]=1
[1][1]=1
[2][2]=1
[3][3]=1
[4][4]=1
[5][5]=1
[6][6]=1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-30
    • 2012-02-27
    • 1970-01-01
    • 2012-06-19
    • 2020-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多