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:
- Given an instance of an
N
-dim array, findN
- Given an instance of an
N
-dim array and ak < N
, find the number of items in dimensionk
- Given an instance of an
N
-dim arrayA
and a vector ofN
integersI
, get or set the item at a position defined by indexes in the vector. For example, if the vector isI = {2, 3, 4}
, there needs to be an operation for obtainingA[2, 3, 4]
from the 3-D arrayA
and a vectorI
. - Given a vector
D
of sizeM
defining dimensions, there needs to be an operation for constructing an array ofM
dimensions, each dimension taking the size of the corresponding item in the vector. For example, if the vectorD = {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 positioni
of the request,F[i] = -1
andD[i] = size(dimension[i])
- For each numeric item
k
at positioni
of the request,F[i] = k
andD[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;
}
2 回答
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.
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.