An interview was asked about ArrayMap, detailed explanation of principle and source code analysis

// 1. Calculate hash code and get index

final int hash;

int index;

if (key == null) {

// If empty, take 0 directly

hash = 0;

index = indexOfNull();

} else {

// Otherwise take Object.hashCode()

hash = mIdentityHashCode? System.identityHashCode (key): key.hashCode ();

index = indexOf(key, hash);

}

// 2. If the index is greater than or equal to 0, it means that there is the same hash code and the same key before, then directly overwrite

if (index >= 0) {

index = (index<<1) + 1;

final V old = (V)mArray[index];

mArray[index] = value;

return old;

}

// 3. If it is not found, the above indexOf() or indexOfNull() will return a negative number, and this negative number is obtained by negating the index of the position to be inserted, so the negation here becomes the insertion will be performed s position

index = ~index;

// 4. Determine whether expansion is required

if (osize >= mHashes.length) {

final int n = osize >= (BASE_SIZE2) ? (osize+(osize>>1))
Android开源项目《ali1024.coding.net/public/P7/Android/git》
: (osize >= BASE_SIZE ? (BASE_SIZE
2) : BASE_SIZE);

if (DEBUG) Log.d(TAG, "put: grow from " + mHashes.length + " to " + n);

final int[] ohashes = mHashes;

final Object[] oarray = mArray;

// 5. Apply for a new space

allocArrays(n);

if (CONCURRENT_MODIFICATION_EXCEPTIONS && osize != mSize) {

throw new ConcurrentModificationException();

}

if (mHashes.length > 0) {

if (DEBUG) Log.d(TAG, “put: copy 0-” + osize + " to 0");

// copy data into new array

System.arraycopy(ohashes, 0, mHashes, 0, ohashes.length);

System.arraycopy(oarray, 0, mArray, 0, oarray.length);

}

// 6. Free the old array

freeArrays (ohashes, oarray, help);

}

if (index < osize) {

// 7. If the index is within the current size, you need to move the data starting at index to index + 1 to free up the position of index

if (DEBUG) Log.d(TAG, "put: move " + index + “-” + (osize-index)

  • " to " + (index+1));

System.arraycopy(mHashes, index, mHashes, index + 1, osize - index);

System.arraycopy(mArray, index << 1, mArray, (index + 1) << 1, (mSize - index) << 1);

}

if (CONCURRENT_MODIFICATION_EXCEPTIONS) {

if (help! = mSize || index> = mHashes.length) {

throw new ConcurrentModificationException();

}

}

// 8. Then insert hash, key, and code according to the calculated index

mHashes[index] = hash;

mArray[index<<1] = key;

mArray[(index<<1)+1] = value;

mSize ++;

return null;

}

The put method calls several other internal methods, among which the expansion and how to release space and apply for new space are not important from the algorithm layer, as long as you know one thing, the expansion will cause data replication, which will affect Efficient on it.

And the indexOfNull() method and the implementation of the indexOf() method, which are more related to the algorithm. Since the implementation of these two methods is basically the same, only the implementation of indexOf() is analyzed here.

int indexOf(Object key, int hash) {

final int N = mSize;

// Important fast case: if nothing is in here, nothing to look for.

if (N == 0) {

return ~0;

}

int index = binarySearchHashes(mHashes, N, hash);

// If the hash code wasn’t found, then we have no entry for this key.

if (index < 0) {

return index;

}

// If the key at the returned index matches, that’s what we want.

if (key.equals(mArray[index<<1])) {

return index;

}

// Search for a matching key after the index.

int end;

for (end = index + 1; end < N && mHashes[end] == hash; end++) {

if (key.equals(mArray[end << 1])) return end;

}

// Search for a matching key before the index.

for (int i = index - 1; i >= 0 && mHashes[i] == hash; i–) {

if (key.equals(mArray[i << 1])) return i;

}

// Key not found – return negative value indicating where a

// new entry for this key should go. We use the end of the

// hash chain to reduce the number of array entries that will

// need to be copied when inserting.

return ~end;

}

In fact, its original comment has been very detailed, and the detailed steps are:

  • (1) If the current table is empty, return ~0 directly. Note that it is not 0, but the largest negative number.

  • (2) Perform a binary search in the mHashs array to find the index of the hash.

  • (3) If index < 0, it means not found.

  • (4) If index >= 0, and the key at index<<1 in mArray is the same as the key to be found, it is considered to be the same key, indicating that it has been found.

  • (5) If the keys are not the same, it means that the hash codes are the same, then search backward and forward respectively, and return if found. If it is not found, then the inversion of end is the current index position to be inserted.

Let's look back at the put() method. The specific implementation of the put() method is described in detail in the source code. If you are interested, you can read it in detail. The following conclusions can be drawn from the put method:

  • (1) The mHashs array stores all hash codes in ascending order.

  • (2) Determine the storage location of the key and value in the mArrays array by the index value of the hash code in the mHashs array. Generally speaking, index << 1 and index << 1 + 1. To put it simply, it is index * 2 and index * 2 + 1.

  • (3) There may be conflicts in hashCode, how to solve it here? This is determined by steps 3 and 7 above. The third step is to get the position of the index that should be inserted, and the seventh step is that if index < osize, it means that the same hashCode value must already exist in the original mArrays, then all the data is moved back one bit, so that Insert multiple identical hash codes in mHashs and must be connected together, and insert new key and value in mArrays, and finally resolve the hash conflict.

The above conclusion may still make people feel a little dizzy, so let's take a look at the picture below and you will understand.

The above figure shows that when index == 0 and when index == 1, the hash codes are the same, indicating that the hash codes of key1 and key2 are the same, that is, there is a hash conflict. Then, as above, the solution here is to store 2 copies of the hash code and one copy of the key-value.

  • get() method

public V get(Object key) {

final int index = indexOfKey(key);

return index >= 0 ? (V)mArray[(index<<1)+1] : null;

}

The main thing is to calculate the index through indexOfKey(), and the implementation of indexOfKey() is to call indexOfNull() and indexOf(). The specific implementation has been analyzed above. If index >= 0 is returned here, it means that it must be found, then according to the previous rules, in mArray, index<<1 + 1 is the value to be obtained.

  • remove() method

public V remove(Object key) {

final int index = indexOfKey(key);

if (index >= 0) {

return removeAt(index);

}

return null;

}

First calculate the index through indexOfKey() to determine whether it exists, and if so, further call removeAt() to delete the corresponding hash code and key-value.

public V removeAt(int index) {

final Object old = mArray[(index << 1) + 1];

final int osize = mSize;

final "Android study notes summary + latest mobile architecture video + big factory Android interview questions + project actual combat source code handouts" open source int nsize;

// If size is less than or equal to 1, the array length will be 0 after removal. In order to compress memory, mHashs and mArray are directly set to empty arrays here

if (osize <= 1) {

// Now empty.

if (DEBUG) Log.d(TAG, “remove: shrink from " + mHashes.length + " to 0”);

final int[] ohashes = mHashes;

Finally I want to say

Why can't many programmers be architects?
1. Good and healthy career planning is very important, but most people ignore it.
2. The habit of study is very important, and perseverance is the correct solution.
3. The programming thinking has not been improved to a higher level. It is limited to coding and business, and has not considered model selection and expansion
. 4. There is no good architect around to guide and cultivate. The circle you are in has a huge impact on the growth of a programmer.

In the golden nine silver ten interview season, job-hopping season, sorting out interview questions has become my habit for many years! Here, some friends around me and I have specially compiled a systematic and comprehensive learning material for rapid advancement as an Android senior engineer. Covers the basic learning skills of Android - Android senior architects.

Attached: 20 sets of real Android interview questions for first- and second-tier Internet companies (including BAT, Xiaomi, Huawei, Meituan, Didi) that we collected because of the autumn recruitment and my own Android review notes (including Android basic knowledge points, Android extensions) Knowledge points, Android source code analysis, summary of design patterns, Gradle knowledge points, summary of common algorithm problems.)

It includes self-learning programming routes in different directions, interview question collections/facebooks, and a series of technical articles, etc. The resources are continuously updated...
guidance and training. The circle you are in has a huge impact on the growth of a programmer.

In the golden nine silver ten interview season, job-hopping season, sorting out interview questions has become my habit for many years! Here, some friends around me and I have specially compiled a systematic and comprehensive learning material for rapid advancement as an Android senior engineer. Covers the basic learning skills of Android - Android senior architects.

Attached: 20 sets of real Android interview questions for first- and second-tier Internet companies (including BAT, Xiaomi, Huawei, Meituan, Didi) that we collected because of the autumn recruitment and my own Android review notes (including Android basic knowledge points, Android extensions) Knowledge points, Android source code analysis, summary of design patterns, Gradle knowledge points, summary of common algorithm problems.)

[External link image dumping...(img-T9se1sXL-1650444794989)]

It includes self-learning programming routes in different directions, interview question collections/facebooks, and a series of technical articles, etc. The resources are continuously updated...

Guess you like

Origin blog.csdn.net/m0_54883970/article/details/124301793