-2

Which would be better in generics? Seems same to me, but eclipse complains to just plain List, but not with List<Object>.


One relatively simple way is to approach this task as a recursive mapping of K-tuples of dimension N to K-tuples of dimension M < N. Since this is language-agnostic, the following facilities need to be available in your target language:

  1. Given an instance of an N-dim array, find N
  2. Given an instance of an N-dim array and a k < N, find the number of items in dimension k
  3. Given an instance of an N-dim array A and a vector of N integers I, get or set the item at a position defined by indexes in the vector. For example, if the vector is I = {2, 3, 4}, there needs to be an operation for obtaining A[2, 3, 4] from the 3-D array A and a vector I.
  4. Given a vector D of size M defining dimensions, there needs to be an operation for constructing an array of M dimensions, each dimension taking the size of the corresponding item in the vector. For example, if the vector D = {3, 4}, there needs to be an operation that creates a 2-D array with dimensions 3 and 4.

Preprocess the request by constructing vectors F and D as follows:

  • For each "all" item at position i of the request, F[i] = -1 and D[i] = size(dimension[i])
  • For each numeric item k at position i of the request, F[i] = k and D[i] = 0.
  • Create an array for the result by taking all non-fixed indexes and passing them to the array constructor (prerequisite number four above).

Now your recursive procedure should look relatively straightforward:

void RecursiveCopy(Vector F, Vector D, Array S, Vector SI, int sp, Array T, Vector TI, int tp) {
    if (pos != TS.size) {
        if (F[sp] != -1) {
            // This is an "all" dimension
            for (int i = 0 ; i != D[sp] ; i++) {
                SI[sp] = i;
                TI[tp] = i;
                RecursiveCopy(F, D, S, SI, sp+1, T, TI, tp+1);
            }
        } else {
            // This is a fixed dimension
            SI[sp] = F[sp];
            RecursiveCopy(F, D, S, SI, sp+1, T, TI, tp);
        }
    } else {
        // Read from the source at indexes defined by vector SI
        var value = S.get(SI);
        // Write to the destination at indexes defined by vector TI
        T.setValue(TI, value); // Prerequisite 3
    }
}

Your getSubarray would look like this:

Array getSubarray(Array S, Vector<string> request) {
    Vector F = Vector[S.Size]; // The number of dimensions in A; prerequisite 1
    Vector D = Vector[S.Size]; // The number of dimensions in A
    Assert(request.Size == S.Size); // Request must have N items
    int k = 0;
    Vector resDim;
    for (int i = 0 ; i != req.Size ; i++) {
        if (req[i] == "all") {
            k++;
            F[i] = -1;
            D[i] = A.dimensionOf(i); // Prerequisite 2
            resDim.Add(D[i]);
        } else {
            F[i] = ParseInteger(req[i]);
            D[i] = -1;
        }
    }
    Array T = Array(resDim); // Prerequisite #4
    Vector SI = Vector[S.Size];
    Vector TI = Vector[k];
    RecursiveCopy(F, D, S, SI, 0, T, TI, 0);
    return T;
}
4

2 回答 2

3

Parameterzation should be used. It provides the compiler with details for things such as casting and autoboxing.

With this, especially when types other than Object are used, the compiler can handle the casting and ensuring compatibility. Especially with return values and method signatures, the true type parametrized may not be exposed out of bytecode to other classes.

Do note that List<Object> is semantically and programatically almost as useless as List. Make sure that if you can, use a more specific type. If declaring a class or method, make sure to use a proper, specific wildcard.

于 2013-07-08T21:48:30.010 回答
1

Neither. It is better to specify the specific generic type of the list contents if possible. At the very least a common interface should be used.

于 2013-07-08T21:49:09.920 回答