It is enough to read this article on Java collections!

introduce

Java collections, also known as containers, are mainly derived from two interfaces:
Collection and Map

As the name suggests, containers are used to store data.

So the difference between these two interfaces is:

Collection stores a single element;
Map stores key-value key-value pairs.
That is, single dogs are placed in the Collection, and couples are placed in the Map. (So ​​where do you belong?

Learning these collection frameworks, I think there are 4 goals:

Clarify the corresponding relationship between each interface and class;
for each interface and class, be familiar with the commonly used API;
for different scenarios, be able to choose the appropriate data structure and analyze the advantages and disadvantages;
learn the design of the source code, and you must be able to answer the interview.

notice
List<List> ret = new ArrayList<>();
System.out.println(ret.toString());//is [] instead of [[]]

Collection

insert image description here

common operation

The collection of operations is nothing more than four categories of "addition, deletion, modification and query", also called CRUD:

Create, Read, Update, and Delete.

Then I also divide these APIs into these four categories:

Function method
increase add()/addAll()
delete remove()/ removeAll()
change In the Collection Interface, if you don’t delete first and then add it, you just change it.
check contains()/ containsAll()
other isEmpty()/size()/toArray()

Implement classes List, Set, queue

Let's look at the top-level Collection first.
insert image description here

  • list is ordered and repeatable
  • set is unordered and non-repeatable
  • queue first in first out

List

insert image description here
There are two ways to implement List: LinkedList (linked list implementation) and ArrayList (array implementation). The most frequently asked question during interviews is how to choose these two data structures.

For this type of selection problem:
one is to consider whether the data structure can complete the required functions;
if it can be completed, the other is to consider which is more efficient.

The difference between linkedlist and arraylist

Function method ArrayList LinkedList
increase add(E e) O(1) O(1)
increase add(int index, E e) O(n) O(n)
delete remove(int index) O(n) O(n)
delete remove(E e) O(n) O(n)
change set(int index, E e) O(1) O(n)
check get(int index) O(1) O(n)

Although ArrayList may be expanded, the amortized time complexity is still O(1).

The biggest difference between arrays and linked lists is that arrays can be accessed randomly (random access).

This feature makes it possible to get the number at any position in the array through the subscript in O(1) time, but the linked list cannot do it, and can only traverse one by one from the beginning.

That is to say, for the two functions of "Change and Check", because the array can be accessed randomly, the efficiency of ArrayList is high.

What about "additions and deletions"?

If you don't consider the time to find this element,

Due to the physical continuity of the array, when adding and deleting elements, it is okay at the end, but other places will cause subsequent elements to move, so the efficiency is low; while the linked list can easily disconnect the connection with the next element , directly insert new elements or remove old elements.

But, in fact, you can't ignore the time to find the element. . . And if it is operated at the end, ArrayList will be faster when the amount of data is large.

so:

  • Change the check to select ArrayList;
  • Add and delete the selection ArrayList at the end;
  • In other cases, if the time complexity is the same, it is recommended to choose ArrayList, because the overhead is smaller, or the memory usage is more efficient.

Vector与Stack

As the last knowledge point of List, let's talk about Vector. This is also an age-revealing post, and all the people who have used it are big guys.

Like ArrayList, Vector also inherits from java.util.AbstractList, and the bottom layer is also implemented with arrays.

But it's deprecated now because...it adds too much synchronized!

Any benefit comes at a price. The cost of thread safety is low efficiency, which can easily become a bottleneck in some systems, so now everyone no longer adds synchronized at the data structure level, but transfers this task to our programmers = =

Then the common interview question: What is the difference between Vector and ArrayList? It is not comprehensive enough to answer only this.

insert image description here

  1. It is the thread safety issue that has just been mentioned;
  2. It is the difference between how much to expand when expanding.

So how much is the expansion? You have to look at the source code
insert image description here
. This is the expansion implementation of ArrayList. This arithmetic right shift operation is to move the binary number of this number to the right by one bit, and complement the sign bit on the leftmost side. However, because the capacity has no negative numbers, it is still filled with 0. Then shift it to the right
. The effect of the bit is to divide by 2, then the defined new capacity is 1.5 times the original capacity.

Let's look at Vector again:
insert image description here
because we usually don't define capacityIncrement, it doubles the capacity by default.

If you answer these two points, you will be fine.

Stack - deprecated and suggested ArrayDeque

Stack is semantically a last-in-first-out (LIFO) linear data structure.

There are many high-frequency interview questions that use the stack, such as the problem of receiving water. Although the optimal solution is to use double pointers, using the stack is the most intuitive solution and you need to understand it. I will write it when I have the opportunity.

So how is the stack implemented in Java?

Although there is a Stack class in Java, the official documents say that it is not allowed to use it!

A more complete and consistent set of LIFO stack operations is provided by the Deque interface
and its implementations, which should be used in preference to this class.

The reason is also very simple, because Vector has been deprecated, and Stack inherits from Vector.

Then if you want to realize the semantics of Stack, use ArrayDeque:

Deque<Integer> stack = new ArrayDeque<>();

Queue & Deque

Queue is a linear data structure that enters at one end and exits at the other end; while Deque can enter and exit at both ends.

insert image description here

LinkedList is also the implementation of List

Implementation class

There are three implementation classes for them:
insert image description here

  • If you want to implement the semantics of "ordinary queue - first in, first out", use LinkedList or ArrayDeque to achieve it;
  • If you want to implement the semantics of "priority queue", use PriorityQueue;
  • If you want to implement the semantics of "stack", use ArrayDeque.

API

Basic API

The Queue interface in Java is a bit of a pitfall.
The APIs of Queue and Deque have a time complexity of O(1), which is an amortized time complexity to be precise.
Generally speaking, the semantics of queues are first-in-first-out (FIFO), but there is an exception here, that is, PriorityQueue, also called heap, does not come out in the order of time it goes in, but goes out in accordance with the specified priority, and its operation It is not O(1), and the calculation of time complexity is a bit complicated, so we will open a separate article later.

It has two sets of basic APIs, the basic functions are the same, but:

One set throws an exception; the other returns a special value.

Function throw exception return value
increase add(e) offer(e)
delete remove() poll()
look element() peek()

Why does it throw an exception?

For example, if the queue is empty, remove() will throw an exception, but poll() will return null; element() will throw an exception, and peek() will return null.

How can add(e) throw an exception?

Some Queues have capacity limitations, such as BlockingQueue, if it has reached its maximum capacity and will not expand, it will throw an exception; but if offer(e), it will return false.

How to choose? :

  • First of all, use the same set of APIs if you want to use them, and they must be unified before and after;
  • Second, according to demand. If you need it to throw an exception, use the one that throws an exception; but it is basically not used when doing algorithm problems, so just choose the group that returns a special value.
And the API

Deque can be entered and exited at both ends. Naturally, there are operations on the First end and operations on the Last end. Then each end has two groups, one group throws an exception, and the other group returns a special value:

Function throw exception return value
increase addFirst(e)/ addLast(e) offerFirst(e)/ offerLast(e)
delete removeFirst()/ removeLast() pollFirst()/ pollLast()
look getFirst()/ getLast() peekFirst()/ peekLast()

The same is true when using it, and use the same group if you want to use it.

ArrayDeque or LinkedList

One sentence summary So , as long as you don't have to store null values ​​or use versions before java6, choose ArrayDeque!

How to choose LinkedList or ArrayDeque when implementing common queue?

Take a look at the high-voted answer on StackOverflow[2]:
insert image description here
In summary, it is recommended to use ArrayDeque because of its high efficiency, and LinkedList will have other additional overhead (overhead).

What are the differences between ArrayDeque and LinkedList?
insert image description here
Still under the same question just now, this is the best summary I think:

ArrayDeque is an expandable array, and LinkedList is a linked list structure;
ArrayDeque cannot store null values, but LinkedList can;
ArrayDeque is more efficient when adding and deleting operations at the head and tail, but LinkedList is only when an element in the middle is to be removed and Removal after the element has been found is O(1);
ArrayDeque is more efficient in terms of memory usage.
So, as long as you don't have to store null values, choose ArrayDeque!

So if a very senior interviewer asks you, under what circumstances should you choose to use LinkedList?

Answer: Before Java 6. . . Because ArrayDeque is only available after Java 6. .
For the sake of version compatibility, we have to make some compromises in actual work. .

Set

It is consistent with the concept of "set" learned in mathematics. It is unordered and non-repetitive.
insert image description here

Common implementation classes

There are three commonly used implementation classes for Set:

  • HashSet: The key of Hashmap is used to store elements. The main feature is that it is out of order, and the basic operations are O(1) time complexity, which is very fast.

  • LinkedHashSet: This is a structure of HashSet + LinkedList, which is characterized by the time complexity of O(1) and the ability to preserve the order of insertion .

  • TreeSet: It adopts red-black tree structure, which is characterized by being orderly, and can be sorted by natural sorting or custom comparator ; the disadvantage is that the query speed is not as fast as HashSet.

Principle and Details

HashSet implements Cloneable and Serializable interfaces.

  • Cloneable: implement the clone() method to realize the clone function
  • Serializable: Indicates that it can be serialized for transmission.

The bottom layer of HashSet is realized through HashMap
. HashMap is realized through array, linked list and red-black tree.

The underlying implementation of each Set is actually the corresponding Map: (I don’t understand it and I’ll add it later)
The value is placed on the key in the map, and a PRESENT is placed on the value. It is a static Object, which is equivalent to a place holder. Each key All point to this object.
Then the specific implementation principle, the four operations of adding, deleting, modifying and checking, as well as hash conflicts, hashCode()/equals() and other issues have all been discussed in the HashMap article, so I won’t go into details here.

Guess you like

Origin blog.csdn.net/S_ZaiJiangHu/article/details/129536087