读取具有未知维度的数组中的值范围

时间:2016-07-26 12:37:39

标签: java arrays multidimensional-array

我正在寻找一种方法来读取未知维度(非长度)数组中的一系列元素。

客户端可以发送对象的读取请求并指定要读取的范围。输入字符串可以是这样的:" 1:2:3:2,2:3:1:4"例如。这意味着他想要读取数组中[1] [2] [3] [2]到[2] [3] [1] [4]范围内的元素。

为了阅读具体元素,我创建了这个函数:

public Object readValue(Object obj,int[] positions ) {
    Object value = null;    //Result
    int objDimension = getDimension(obj); //Dimesion of the array
    System.out.println("Dimension: " + objDimension );
    try {
        Object[] aux = (Object[]) obj;
        for (int i = 0; i < objDimension - 1; i++) {
            int pos = positions[i];
            aux = (Object[]) aux[pos];
        }
        value = aux[positions[objDimension - 1]];
        System.out.println("Result: " + value);
    } catch (ArrayIndexOutOfBoundsException e) {
        // TODO: Send a fault to the client.
        System.out.println("Error: "+e.getMessage());
    }
    return value;
}

public static int getDimension(Object value) {
    Class<?> clazz = value.getClass();
    String className = clazz.getName();
    int dimension = 0;
    for (int i = 0; i < className.length(); i++) {
        if (className.charAt(i) != '[') {
            dimension = i;
            break;
        }
    }
    return dimension;
}


//Example.
public static void main(String[] args) {
    // TODO code application logic here
    TestMultiDimensioNRead test = new TestMultiDimensioNRead();
    Integer[][][][] testSubject = new Integer[5][2][4][];

    testSubject[0][0][2] = new Integer[8];
    testSubject[0][0][0] = new Integer[15];
    testSubject[0][0][1] = new Integer[20];
    testSubject[0][0][3] = new Integer[2];
    testSubject[1][1][2] = new Integer[7];
    testSubject[1][1][2][0] = 80;
    test.readValue(testSubject,new int[]{1, 1, 2, 0});
}

我在想一个好方法可能是计算每个尺寸长度之间的差异。

如果有人能提出好主意,我真的很感激。

提前致谢。

编辑1:此问题中发布的代码确实读取了未知维度数组中给定位置的值。我的问题是阅读给定点之间的所有元素。这可能在最初的问题中并不清楚。

2 个答案:

答案 0 :(得分:1)

您可以使用递归解决方案:

public class Test {
    private class TestMultiDimensioNRead {
        public Integer readValue(Object testSubject, int[] coordinates) {
            return readValue(testSubject, coordinates, 0);
        }

        private Integer readValue(Object testSubject, int[] coordinates, int which) {
            if (testSubject instanceof Object[]) {
                Object[] subject = (Object[]) testSubject;
                if (coordinates.length > which + 1) {
                    return readValue(subject[coordinates[which]], coordinates, which + 1);
                } else {
                    return (Integer) subject[coordinates[which]];
                }
            } else {
                // Throw some sort of exception?
                return -1;
            }
        }

        public Iterator<Integer> readValues(Object testSubject, int[] coordinates, int count) {
            return readValues(testSubject, coordinates, count, 0);
        }

        private Iterator<Integer> readValues(Object testSubject, int[] coordinates, int count, int level) {
            if (testSubject instanceof Object[]) {
                Object[] subject = (Object[]) testSubject;
                if (coordinates.length > level + 1) {
                    return readValues(subject[coordinates[level]], coordinates, count, level + 1);
                } else {
                    return new Iterator<Integer>() {
                        int i = 0;
                        Integer[] intSubject = (Integer[]) subject;

                        @Override
                        public boolean hasNext() {
                            return i <= count;
                        }

                        @Override
                        public Integer next() {
                            return intSubject[coordinates[level] + (i++)];
                        }
                    };
                }
            } else {
                // Throw some sort of exception?
                return null;
            }
        }

    }

    public void test() {
        TestMultiDimensioNRead test = new TestMultiDimensioNRead();
        Integer[][][][] testSubject = new Integer[5][2][4][];

        testSubject[0][0][2] = new Integer[8];
        testSubject[0][0][0] = new Integer[15];
        testSubject[0][0][1] = new Integer[20];
        testSubject[0][0][3] = new Integer[2];
        testSubject[1][1][2] = new Integer[7];
        testSubject[1][1][2][0] = 80;
        testSubject[1][1][2][1] = 79;
        testSubject[1][1][2][2] = 78;
        Iterator<Integer> them = test.readValues(testSubject, new int[]{1, 1, 2, 0}, 3);
        for (Integer x = them.next(); them.hasNext(); x = them.next()) {
            System.out.println(x);
        }
        System.out.println();

    }

    public static void main(String args[]) {
        try {
            new Test().test();
        } catch (Throwable t) {
            t.printStackTrace(System.err);
        }
    }
}

按预期打印80

在理智检查方面可能还有更多工作要做,但这似乎有效。

答案 1 :(得分:0)

找到了做到这一点的方法,也许它在某些方面对某人有所帮助。 我没有包括任何支票,这更像是一个测试案例,看它是否有效。

public class TestReadMultiDimensionArray {

private int[] startPosition;                //Start position.
private int[] endPosition;                  //End position.
private boolean inRange = false;            //If the current position is in range.
private List<Object> result;                //List to store the values we find.

public TestReadMultiDimensionArray() {
    result = new ArrayList<>();
}

public static void main(String[] args) {
    TestReadMultiDimensionArray test = new TestReadMultiDimensionArray();
    Integer[][][][] testSubject = new Integer[2][2][4][];
    //(0,0,y,z)
    testSubject[0][0][0] = new Integer[]{1};                                    //(0,0,0,0)
    testSubject[0][0][1] = new Integer[]{2};                                    //(0,0,1,0)
    testSubject[0][0][2] = new Integer[]{3};                                    //(0,0,2,0)
    testSubject[0][0][3] = new Integer[]{4};                                    //(0,0,3,0)
    //(0,1,y,z)
    testSubject[0][1][0] = new Integer[]{5};                                    //(0,1,0,0)
    testSubject[0][1][1] = new Integer[]{6};                                    //(0,1,1,0)
    testSubject[0][1][2] = new Integer[]{7, 8, 9};                              //(0,1,2,0) (0,1,2,1) (0,1,2,2)
    testSubject[0][1][3] = new Integer[]{10};                                   //(0,1,3,0)
    //(1,0,y,z)
    testSubject[1][0][0] = new Integer[]{11, 12};                               //(1,0,0,0)..
    testSubject[1][0][1] = new Integer[]{13, 14, 15};
    testSubject[1][0][2] = new Integer[]{16, 17, 18};
    testSubject[1][0][3] = new Integer[]{19, 20, 21};                           //..(1,0,3,2)
    //(1,1,y,z)
    testSubject[1][1][0] = new Integer[]{22, 23};                               //(1,1,0,0)..
    testSubject[1][1][1] = new Integer[]{24, 25, 26};
    testSubject[1][1][2] = new Integer[]{27, 28, 29, 30, 31, 32, 33, 34};
    testSubject[1][1][3] = new Integer[]{35, 36};                               //..(1,1,3,1)
    //Launch the test.
    test.readValue(testSubject);
}

/**
 *
 * @param obj The Array from where we want to get the data.
 */
public void readValue(Object obj) {
    //Where should it start.
    startPosition = new int[]{0, 1, 0, 0};
    //Where should it stop.
    endPosition = new int[]{1, 1, 1, 2};
    System.out.println("Start Position:" + Arrays.toString(startPosition) + " End Position:" + Arrays.toString(endPosition));
    int[] currentPosition = new int[]{-1, -1, -1, -1};

    //Call to the method.
    testRead((Object[]) obj, 0, currentPosition);
    //Result to array.
    Object[] arrayToReturn = result.toArray(new Object[0]);
    System.out.println("Result: " + Arrays.toString(arrayToReturn));
}

/**
 * Recursive method that looks for the values in a multi-dimensional array, in a given range. /!\ No checks are implemented here, wrong input can end in a
 * StackOverFlow.
 *
 * @param obj The array in Object[] form.
 * @param currentDimension The dimension we are currently in.
 * @param result The reference to the list that will store all the values we found.
 * @param currentPosition The current position we are in.
 */
private void testRead(Object[] obj, int currentDimension, int[] currentPosition) {
    for (int i = 0; i < obj.length; i++) {
        currentPosition[currentDimension] = i;
        if (Arrays.equals(startPosition, currentPosition) && currentDimension == (currentPosition.length - 1)) {
            //Found the start position.
            System.out.println("############ START ############");
            inRange = true;
        }

        if ((i >= startPosition[currentDimension] && i <= endPosition[currentDimension]) || inRange == true) {
            //We are in the write track to get to the values we are looking for.
            if (obj[i] instanceof Object[]) {
                //The data contained in the cell is an array.
                testRead((Object[]) obj[i], currentDimension + 1, currentPosition);
            } else {
                //The data contained in the cell is a scalar. This is what we where looking for.
                System.out.println(Arrays.toString(currentPosition) + " Data: " + obj[i]);
                result.add(obj[i]);
            }
        }

        if (Arrays.equals(endPosition, currentPosition) && currentDimension == (currentPosition.length - 1)) {
            //Found the end position.
            System.out.println("############ END ############");
            inRange = false;
        }
    }
}

}

欢迎提出更好代码的任何问题或想法。