[英]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/
我的問題是:
請注意,您不需要創建Index
類。 您需要的類型已經存在 。
從IntBuffer.compareTo
的文檔中:
通過按字典順序比較兩個int緩沖區的其余元素序列來比較兩個int緩沖區,而不考慮每個序列在其相應緩沖區中的開始位置。
因此,如果包裝包含索引的整數數組並將位置和限制保持為默認值,則緩沖區將提供所需的行為。
如果考慮到在Java中,則每個多維數組也是Object[]
的實例,無論它們的基本類型如何,都可以以一般方式執行數組到映射的轉換。 即,類型int[][]
是Object[]
的子類型,其元素是int[]
實例,后者是Object
的子類型。 此外, Object[][]
是Object[]
的子類型,其元素是Object[]
類型,而Object[]
是Object
的子類型。
因此,您可以使用與Object[]
相同的方式處理所有維度,並且只需關心最后一個維度的實際類型,對於任何n維int
數組,該類型始終為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.