1

This issue is the 2 issue of the [ online interviewer ] series of articles, mainly Java List high-frequency interview questions.

Reply to [ interview ] Get Dabin's well-organized interview manual of the big factory, which has helped many small partners to win the big factory offer!

Interview scene

Interviewer : Hello, I'm interviewer xxx, are you Dabin?

: Hello, interviewer, I am Dabin

Interviewer : Is it convenient for an interview now?

: Mmmm, yes

: Let's start the interview now

Interviewer : Seeing that you are familiar with collections on your resume, do you know Java List?

: Well, List is an interface, and common implementation classes are ArrayList and LinkedList

Interviewer : talk about the difference between these two implementation classes?

Monologue: Old Baguwen Haha

: The underlying data structure of ArrayList is an array, which supports subscript access and can query data quickly. The default initial value is 10, and the capacity will be expanded when the capacity is insufficient.

: The underlying data structure of LinkedList is a linked list, adding elements to the end of the linked list does not require expansion

Interviewer : Well, you mentioned the expansion of ArrayList just now, can you tell me in detail?

Monologue: Good guy, I knew you would ask this, and the eight-part essay is ready.

: ArrayList expansion source code is implemented as follows:

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  //扩容
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

: As you can see, in the grow method, the capacity of the array is expanded to 1.5 times the original capacity.

: For example, if the initialized value is 8, when the ninth element is added, it is found that the array space is not enough, and the capacity will be expanded, and the capacity will be 12 after the expansion.

: After the expansion, the Arrays.copyOf() method will be called to copy the array.

Interviewer : Well, yes, what scenarios are ArrayList and LinkedList suitable for?

: For the get and set methods of random index access, ArrayList is faster than LinkedList. Because ArrayList finds elements directly through the array subscript; LinkedList needs to move the pointer to traverse each element until it is found.

: LinkedList is faster than ArrayList for adding and deleting elements. Because ArrayList may expand and copy the array when adding and deleting elements; and LinkedList's adding and deleting operations only need to modify the pointer.

: Therefore, ArrayList is suitable for scenarios with many queries and few additions and deletions. LinkedList is suitable for scenarios with few queries and many additions and deletions

Interviewer : talk about the difference between Set and List?

: List accesses elements by index, in order, elements are allowed to be repeated, and multiple nulls can be inserted; Set cannot store repeated elements, and out of order, only one null is allowed to be inserted.

: The underlying implementation of List has two methods: array and linked list; Set is implemented based on Map, and the element value in Set is the key value of Map.

Interviewer : Know Vector?

: Well, Vector is the underlying structure and an array, and now Vector is basically not used because the efficiency of vector operation is relatively low. Compared with ArrayList, it is thread-safe, and its capacity is doubled when expanding.

Interviewer : Well, do you know any thread-safe Lists?

: You can use the Collections.synchronizedList() method to return a thread-safe List.

: There is another way, using CopyOnWriteArrayList.

Interviewer : , you mentioned CopyOnWriteArrayList just now, how about it?

Monologue: This is too convoluted. A disagreement is the underlying principle...

: CopyOnWriteArrayList is a thread-safe List, and the bottom layer is implemented by copying the array.

: The so-called CopyOnWrite is copy-on-write.

: When we add elements to the container, we do not directly add to the container, but first copy the current container, copy a new container, and then add elements to the new container. The reference to the original container points to the new container.

: The advantage of this is that the CopyOnWrite container can be read concurrently without locking, because the current container will not be modified.

public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock(); //add方法需要加锁
    try {
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements, len + 1); //复制新数组
        newElements[len] = e;
        setArray(newElements); //原容器的引用指向新容器
        return true;
    } finally {
        lock.unlock();
    }
}

Interviewer : So can you talk about the disadvantages of CopyOnWriteArrayList?

: There are two main problems.

: Memory usage problem. Due to the copy-on-write mechanism of CopyOnWrite, when a write operation is performed, the memory of two objects will reside in the memory at the same time.

: The CopyOnWrite container cannot guarantee the real-time consistency of data, and may read old data.

: Well, yes.

Interviewer : asked some common development problems, how to sort the List?

: You can use the sort method of the list itself, or use the Collections.sort(list) method.

Interviewer : How does remove an element while traversing an ArrayList?

: If you use foreach to delete elements, it will cause a fast-fail problem. You can use the iterator's remove() method to avoid the fast-fail problem.

Iterator itr = list.iterator();
while(itr.hasNext()) {
      if(itr.next().equals("dabin") {
        itr.remove();
      }
}

Interviewer : The basics are not bad! go back and wait for notification

: ok thank you

Monologue: Go back and wait for the notice? It won't be cold...


程序员大彬
468 声望488 粉丝

非科班转码,个人网站:topjavaer.cn