Your idea is to implement a "resizable" array upon a java array (which has a fixed size). The first nElem elements in this fixed array are your logical array. Now you want to be able to set and remove elements to and from this logical array:
[00] [01] [02] [03] [04] [05] [06] [07] [08] [09] ... [99] // physical array
[00] [01] [02] [03] [04] [05] [06] [07] [08] // logical array, nElem = 9
Insert '99' at (logical) position 04
[00] [01] [02] [03] [99] [04] [05] [06] [07] [08] // nElem = 10
Delete value at (logical) position 03
[00] [01] [02] [99] [04] [05] [06] [07] [08] // nElem = 9
The size of the java array is still 100 (it's fixed), the size of the logical array (nEleme) has to be adjusted after each insert and remove operation.
If you insert an element, you have to "shift" some elements "to the right" (and increment nElem). You'll need a for loop and a counter (j) for this. The same happens if you want to remove an element, you have to "shift" elements "to the left" and again you need a counter.
Why do we use j and nElems to search an array.
To search for an item in an (unsorted) collection (array, set, ..) you'll have to look at each element, maybe starting at index=0 up to index=(nElem-1). If the value at the current position matches your search criteria (example: is-equal-to), you can break the search. j stores this actual index, nElem the size of the (logical) array so (nElem-1) the index of the last element in this (logical) array)
Why do we again assign j to k for deletion? Can't we delete it from j itself?
Merely for readbility. This will work too, but is much harder to understand.
for(j = 0; j < nElems; j++) {
if(arr[j] == searchKey) {
break;
}
}
for(;j < nElems-1; j++) { // note the missing initialzing value for the loop
arr[j] = arr[j+1];
}