2016-09-16 56 views
2

我有几个以不同组合出现的二维数组,其中一个定义了中心,另外八个逻辑(而非物理上)放置在左侧,右侧,顶部,右上角等等。 'new array'的访问方式如下: 如果x和y索引位于中心数组的边界内,则访问中心数组。如果索引超出边界(或者是高于或者高于< 0),则访问适当的相邻数组(例如,对于x < 0和y < 0,左上角的数组被访问)。Java在逻辑上连接数组

在此刻我正在手动解决数组索引的重新映射。下面是一个例子(没有必要了解情况,我只是想表明所描述的过程中的结构):

public float noiseValueForCorner(int x, int y, int colorRight, int colorLeft, int colorTop, 
int colorBottom, int tileLeftUp, int tileRightUp, int tileLeftLower, int tileRightLower) 
{ 
// Out of bounds 
    if (x < -K2 || y < -K2 || x >= 4*K || y >= 4*K) 
     return -1.0f; 

if (y >= 0 && y < K2) 
{ 
    // corner itself 
    if (x >= 0 && x < K2) 
    return CornerNoise.noise[x][y]; 
    // left color 
    else if (x < 0 && colorLeft >= 0) 
    return ColorNoise[colorLeft].noise[K2-y-1][N2K+x]; 
    // right color 
    else if (x >= K2 && colorRight >= 0) 
    return ColorNoise[colorRight].noise[K2-y-1][x-K2]; 
} 
else if (y < 0) 
{ 
    // top color 
    if (x >= 0 && x < K2 && colorTop >= 0) 
    return ColorNoise[colorTop].noise[x][N2K+y]; 
     // top left tile 
    else if (x < 0 && tileLeftUp >= 0) 
    return TileNoise[tileLeftUp].noise[N2K+x][N2K+y]; 
    // top right tile 
    else if (x >= K2 && tileRightUp >= 0) 
    return TileNoise[tileRightUp].noise[x-K2][N2K+y]; 
} 
else //if (y >= K2) 
{ 
    // bottom color 
    if (x >= 0 && x < K2 && colorBottom >= 0) 
    return ColorNoise[colorBottom].noise[x][y-K2]; 
    // bottom left tile 
    else if (x < 0 && tileLeftLower >= 0) 
    return TileNoise[tileLeftLower].noise[N2K+x][y-K2]; 
    // bottom right tile 
    else if (x >= K2 && tileRightLower >= 0) 
    return TileNoise[tileRightLower].noise[x-K2][y-K2]; 
} 

return 2.0f; 
} 

的问题是,由于这种方法的许多人呼吁我的整个程序是相当慢。我想知道是否有更好的方法来做到这一点。我想到了一些有效的方法来将索引转换为单个数组的内存地址,以获得一个新数组(因为数组访问完成得相当快)。

+0

阵列内,将其卸载到一个线程的帮助? –

+0

阵列或其放置位置更改的频率以及您访问“放置配置”的频率? – Robert

+0

除了手动编码所有情况下繁琐的手动编码之外,所显示的代码不一定很慢。使用分析器查找使用频率和瓶颈。 FindBugs也可能会产生一些影响。 –

回答

0

您可以通过一些简单(因此快速)的算术运算来映射坐标。任何其他边界检查都不需要ifs。

首先简单情况,9点的阵列,同一尺寸的正方形:

做一个[A X A]的数组的数组。您可以通过坐标a来选择数组,您可以通过获取坐标相对于a的模数来获得数组中的索引。作为一个例子:如果你有9个数组(这是一个3x3的数组数组),每个5x5,你的原始索引将从(-5,-5)到(5,5)运行。在这种情况下通过添加5来标准化可能是最简单的,通常添加最低的索引值。因此,示例索引现在从(0,0)到(10,10)

查找数组除以5.结果是要使用的数组的索引,范围(0,0)到(2,2)。您现在可以访问适当的数组。将该结果称为x和y:nx,ny。

theArrays[nx, ny] 

数组中的索引只是通过使用%运算符和数组维数获得的。

实施例:(8,-4)标准化为(13,1)接入

(theArrays[2, 0])[3, 1]; 

扩展这对其中中央阵列是大和外阵列是小的时候,我们通过将归一化进行管理的情况下中央阵列的尺寸。实际上,较低/左侧的阵列被翻译而留下空隙。

作为一个例子,中央阵列是5 x 5,角落外部阵列是3 x 3,中央外部阵列是5 x 3或3 x 5.左下角阵列将从[-3,-3 ]到[0,0]标准化会移动左下角的数组以从[2,2]开始。

在外部数组大于中央数组的情况下,算术会稍微复杂一些,但仍可以在没有if语句的情况下完成。

作为示例,中心阵列为3 x 3,外部阵列为5 x 5,3 x 5和5 x 3。仅考虑一个维:

array 0   1  2 
-5 -4 -3 -2 -1 | 0 1 2 | 3 4 5 6 7 

所以输入范围从-5 ... 7.

我们要映射到阵列0,1或2

-5至-1 => 0,0到2 => 1,3到7 => 2

一种方法是使用查找表。这可能是最快的。为了记录这里有一些算术来做到这一点。数组的大小E和C(边缘和中心),请求的索引我

index of array = (2 * ((i + e)/(e + c))) + (((i + e) % (e + c))/e) 

sample values: 
     -5 => 0 + 0 => 0 
     -3 => 0 + 0 => 0 
     -1 => 0 + 0 => 0 
     0 => 0 + 1 => 1 
     2 => 0 + 1 => 1 
     3 => 2 + 0 => 2 

对于指数如果这个特殊的部分是缓慢的那就更简单了

index within array = ((i + e) % (e + c)) % e 

     -5 => 0 % 5 => 0 
     -3 => 2 % 5 => 2 
     -1 => 4 % 5 => 4 
     0 => 5 % 5 => 0 
     2 => 7 % 5 => 2 
     3 => 0 % 5 => 0 
+0

这通常是一个好主意,但是我的数组并没有相同的大小。更准确地说,该中心具有_a_ x_a_ elemens,左右数组具有_b_ x _a_元素,顶部和底部数组_a_ x _b_元素和其他四个元素(左上角,右上角......)的大小的_b_ x _b_。因此,我不能简单地将索引除以一个数组的宽度或高度。 –

+0

是b djna

+0

如果b> a,也可以想出一个很好的算术方法。我会在明天再回答。总结:首先除以(a + b),然后用b除结果。 – djna