Handwritten ArrayList core source code

original
2021/07/02 16:57
Reading 4.2K

Handwritten ArrayList core source code

ArrayList is a commonly used data structure in Java, not only ArrayList, but also LinkedList, HashMap, LinkedHashMap, HashSet, Queue, PriorityQueue, etc. We will write the core source code of these commonly used data structures and reveal the core principles with as little code as possible.

Now let's write the core source code of ArrayList

First, let's define a QArrayList. Don't ask why it is called QArrayList, because I wrote Qt before, that's all. Source code public class<T> QArrayList The bottom layer of ArrayList in Java uses an Object [] structure to save data. We also need to define an Object [] attribute.

We also need to define a default data size for use when calling the default constructor. private final int DEFAULT_LIST_SIZE = 8;

Also define a int mSize Variables, MSize is 0 by default Represents the index of the next array that can store data Represents the index of the next array that can store data Represents the index of the next array that can store data Important things are to be repeated for 3 times

So far our classes are as follows:

 public class QList<T> { //The size of the default array private final int DEFAULT_LIST_SIZE = 8; //Where to store data private Object[] mData; //Index of the next current array that can store data private int mSize; ...... }

Well, there is also an array for storing data, and the index of the next current array for storing data is also available. The bottom layer of the ArrayList uses arrays to store data, so there will be a problem. What can we do if the array is full and we store data in it? ArrayList is to create a new array, and the size of the new array is twice the size of the original array, so we do the same.

At this point, we implement the core methods of add, get, remove, resize, etc. The complete code of QArrayList is as follows:

 public class QArrayList<T> { //The size of the default array private final int DEFAULT_LIST_SIZE = 8; //Where to store data private Object[] mData; //Index of the next current array that can store data private int mSize; public QArrayList() { //New An array used to store mData = new Object[DEFAULT_LIST_SIZE]; //The index of the next current array that can store data is 0 mSize = 0; } public QArrayList(int capacity){ if(capacity <= 0 || capacity > Integer. MAX_VALUE){ throw new RuntimeException("invalid capacity"); } mData = new Object[capacity]; mSize = 0; } //Returns how many elements have been stored in the array at that time public int size() { return mSize; } //Returns the total size of the array. In fact, it is not necessary to provide this interface externally. Here we are just for demonstration public int capacity() { return mData.length; } //Add an element public void add(T e) { //It is not allowed to add an empty element if(e == null){ return; } //If the current array is full, it will be expanded twice as much as the original array if (mSize >= mData.length) { //Capacity expansion resize(); } //Add the added element to the array mData[mSize] = e; //At the same time, mSize++points to the next location where data can be stored mSize++; } //Get the element at the specified position. If the position is illegal, throw an exception directly //This is necessary. What we provide is a library //Throw an exception directly to let users know that it is wrong. There is no need to return null //Because this is a library, not a business. Even if the return is null, it is also a business level issue public T get(int position) { if (position < 0 || position >= mData.length) { throw new RuntimeException("position is invalid"); } //It doesn't matter if the position is greater than mSize, because it also returns null, proving that it has not been obtained return (T) mData[position]; } //Delete the element at the specified position public T remove(int position) { //As above, the illegal location directly throws an exception if (position < 0 || position >= mData.length) { throw new RuntimeException("position is invalid"); } //Save the element to be deleted and return the element to be deleted T e = (T) mData[position]; //After deletion, move all the following elements forward for (int i = position + 1;  i < mData.length; i++) { mData[i - 1] = mData[i]; } //Don't forget that mSize needs-- mSize--; //Return deleted elements return e; } //Delete the specified element public boolean remove(T e) { //Because the array may not be full, if the deletion is null, it is unnecessary. We do not allow if (e == null) { return false; } //Find where to delete the element int position = -1; for (int i = 0;  i < mData.length; i++) { if (e == mData[i] || e.equals(mData[i])) { position = i; break; } } //Return if not found if (position == -1) { return false; } //Delete return remove(position) !=  null; } //Capacity expansion, we all expand the capacity by twice private void resize() { Object[] old = mData; mData = new Object[mData.length * 2]; for (int i = 0;  i < old.length; i++) { mData[i] = old[i]; } old = null; } }

The comments have relevant explanations. Let's test them. The test code is as follows:

 public static void main(String[] args) { QArrayList<String> list = new QArrayList<>(); list.add("tom"); list.add("jim"); list.add("lilei"); list.add("hanmeimei"); System.out.println("list.get(2)=" + list.get(2)); System.out.println("list.size()=" + list.size()); for (int i = 0;  i < list.size();  i++) { System.out.println("list.get(" + i + ") = " + list.get(i)); } System.out.println("======================="); System. out. println ("Demonstrate deletion"); list.remove("jim"); for (int i = 0;  i < list.size();  i++) { System.out.println("list.get(" + i + ") = " + list.get(i)); } }

The output is as follows: list. get (2)=lilei list. size()=4 list. get (0)=tom list. get (1)=jim list. get (2)=lilei list. get (3)=hammeimei============Demonstrate the deletion operation list. get (0)=tom list. get (1)=lilei list. get (2)=hammeimei

However, the most important capacity expansion function has not been demonstrated yet. The following is the test code for the capacity expansion demonstration:

 public static void main(String[] args) { //Create a new array with only 2 elements QArrayList<String> list = new QArrayList<>(2); //Print the expanded capacity System. out. println ("before capacity expansion: list. capacity()="+list. capacity()); //We added 4 elements list.add("tom"); list.add("jim"); list.add("lilei"); list.add("hanmeimei"); //Print the expanded capacity System. out. println ("After capacity expansion: list. capacity()="+list. capacity()); //Print for (int i = 0;  i < list.size();  i++) { System.out.println("list.get(" + i + ") = " + list.get(i)); } }

The output is as follows:

Before capacity expansion: list. capacity()=2 After capacity expansion: list. capacity()=4 list. get (0)=tom list. get (1)=jim list. get (2)=lilei list. get (3)=hammeimei

As you can see, we have created a new array with only two elements at the bottom, but we have added four elements. We print out that the capacity of the expanded array is 4, which shows that our expansion mechanism is OK.

These are the core principles of QArrayList. In the next section, we will write the core principles of LinkedList

Expand to read the full text
Loading
Click to lead the topic 📣 Post and join the discussion 🔥
Reward
zero comment
four Collection
zero fabulous
 Back to top
Top