求助:Java中用System.arraycopy将int[][]转为int[]时数组失真
嘿,我一眼就瞅出你代码里的问题啦——不管是原来的嵌套循环,还是后来用System.arraycopy的版本,都在索引计算上栽了跟头,这才导致转换后的数组完全失真~
先说说你原来嵌套循环的小错误
你写的destination[x * width + y] = source[x][y]这里,索引算错啦!咱们的source是3行4列的数组,每行有4个元素,所以第x行第y列的元素,在一维数组里的正确位置应该是x * height + y。
为啥?因为第一行(x=0)的4个元素要占满一维数组的0-3位,第二行(x=1)从4开始到7,第三行(x=2)从8到11,这样刚好填满12个位置。你用x*width的话,x=1时起始位置是3,只能放3个元素,最后一维数组会空出3个位置,肯定不对。
再看System.arraycopy版本的核心问题
这才是导致结果完全混乱的关键:你把System.arraycopy的目标数组起始位置参数写错了!
你写的是source[index].length(也就是固定值4),这意味着每次复制都从一维数组的第4位开始——第一行的元素刚放到4-7,第二行又从4开始覆盖,第三行继续覆盖,最后一维数组里只剩第三行的元素,前面的全被冲没了,结果能对就怪了!
正确的目标起始位置应该是index * height(或者index * source[index].length,因为每行长度都是height),这样第index行的元素会被放到一维数组的index*height到index*height + height的位置,完美承接上一行的结尾,不会重叠覆盖。
修正后的代码来啦!
修正后的嵌套循环版
final int width = 3, height = 4; final int[][] source = new int[width][height]; final int[] destination = new int[width * height]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { // 修正索引计算:用height而不是width destination[x * height + y] = source[x][y]; } }
高效的System.arraycopy版本(修正后)
final int width = 3, height = 4; final int[][] source = new int[width][height]; final int[] destination = new int[width * height]; for (int index = 0; index < source.length; index++) { // 目标起始位置改为index * height,对应每行的正确偏移 System.arraycopy(source[index], 0, destination, index * height, height); }
这样两种方式都能正确把二维数组按行优先的顺序转成一维数组,而且System.arraycopy是Java的native方法,数组规模大的时候性能会比嵌套循环好很多哦~
内容的提问来源于stack exchange,提问作者user9841626

