簡體   English   中英

使用整數數組鍵過濾TreeMap並執行算術運算

[英]Filter TreeMap with integer array key and perform arithmetic operations

我用Java寫了一個復雜的程序,需要管理許多包含整數值的大型稀疏矩陣。 例:

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

為了節省內存,空間等,我決定將此數據存儲在TreeMap中。 我知道有很多庫可以做得更好,但是我會嘗試實現我的個人解決方案。 首先,我創建了一個類Index,用於標識此數組的indes而不知道它們的個數。

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

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

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

顯然,我已使用此類以這種方式定義我的三個Map:

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

現在,我需要將之前創建的矩陣中的數據存儲到那些Maps中。 最簡單的方法是使用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. 關於這個問題有什么建議嗎?

請注意,您不需要創建Index類。 您需要的類型已經存在

IntBuffer.compareTo的文檔中:

通過按字典順序比較兩個int緩沖區的其余元素序列來比較兩個int緩沖區,而不考慮每個序列在其相應緩沖區中的開始位置。

因此,如果包裝包含索引的整數數組並將位置和限制保持為默認值,則緩沖區將提供所需的行為。


如果考慮到在Java中,則每個多維數組也是Object[]的實例,無論它們的基本類型如何,都可以以一般方式執行數組到映射的轉換。 即,類型int[][]Object[]的子類型,其元素是int[]實例,后者是Object的子類型。 此外, Object[][]Object[]的子類型,其元素是Object[]類型,而Object[]Object的子類型。

因此,您可以使用與Object[]相同的方式處理所有維度,並且只需關心最后一個維度的實際類型,對於任何nint數組,該類型始終為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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM