preface
Most programming languages provide array to save objects, and array is one of the most important data structures. However, the length of the array has been defined during initialization, which is immutable and troublesome to use. Therefore, Java inJDK 1.2
The collection framework is added to the version to save and manipulate objects.
The container in Java adopts the idea of “holding objects”, which is mainly composed of inheritanceCollection
AndMap
Two interfaces. Let’s take a look at these two types of containers
- Collection: it is mainly a collection of objects. It mainly stores single elements.
- Map: it mainly stores the relation mapping table about “key value pair”, mainly stores
key-value
The key value is correct.
Collection
Collection
Interface is the main interface, which is further divided intoList
、Set
AndQueue
These three interfaces are inherited fromCollection
, but the functions to be realized are different.List
When storing elements, the insertion order should be maintained;Set
It does not contain repeated elements;Queue
Determine the order in which objects are generated (usually in the same order in which they are inserted) according to the sorting rules.
But because they are inherited fromCollection
Interface, so they all have some of the same operations:
public interface Collection<E> extends Iterable<E> {
In Java 8, the interface also adds a default method:
//Default method newly added in Java 8
That’s allCollection
It’s a new API. After subclass inheritance, these methods are also inherited, but subclasses can be implemented with different data structures.
Iterator & Iterable
Iterator
Is the iterator in Java, which can make the class that implements the interface iterate. Let’s take a lookIterator
Interface:
public interface Iterator<E> {
And what we’re going to learn nextCollection
Interface inheritedIterable
Interface, in whichiterator()
Methods can produceIterator
Object to iterate through the collection
public interface Iterable<T> {
Iterator<T> iterator();
// JDK 1.8
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
Iterable
Interface provides a way to getIterator
Object, so it implementsIterable
The collection of interfaces can still use iterators to traverse and manipulate the objects in the collection.
Let’s use it to realize itIterable
Collection usage of interfacesIterator
Iterator traverses:
LinkedList<String> list = new LinkedList<>();
But this is more troublesome. After JDK 1.8, it is providedfor-each
MethodIterable
Interface object, which is a kind of JavaGrammar sugar
. As follows:
for (String s : list) {
System.out.println(s);
}
ListIterator
Exist inList
In the set, there is a function ratioIterator
More powerful iterators.
public interface ListIterator<E> extends Iterator<E> {
As you can see from the above method,ListIterator
It is a two-way move, and generates indexes to the previous and next elements according to the elements pointing to the current position in the iteratorindex
。
public static void main(String[] args) {
fail-fast
fail-fast
Is a kind of error detection mechanism in Java collection. When multiple threads change the structure of a part of the collection, how can it happenfail-fast
Mechanism, which will be thrown at this timeConcurrentModificationException
Abnormal.
The simplest example is in usefor-each
Delete when traversing syntax:
List<String> list = new ArrayList<>();
list.add("Jan");
list.add(null);
list.add("Feb");
list.add("Mar");
System.out.println(Arrays.toString(list.toArray()));
for (String s : list) {
if (s == null) list.remove(s);
}
System.out.println(Arrays.toString(list.toArray()));
In this way, an error will be reported at runtime
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1042)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:996)
at xxx.xxx.Xxxx.java:22)
We all know thatfor-each
It’s just a kind ofGrammar sugar
In itselfIterator
Operation, let’s see the source code in the error report above:
public E next() {
stayIterator
Ofnext
During operation, the operation will be checked:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
andmodCount
The value of theremove
Modify during operation:
public E remove(int index) {
bringmodCount
AndexpectedModCount
The values of cannot be equal, so thejava.util.ConcurrentModificationException
Exception, terminate traversal.
If we want to solve the above problems, we give two solutions
useIterator
Operation to delete or JDK 1.8 newremoveIf
Default method.
Iterator<String> iterator = list.iterator ();
It can also be usedCopyOnWriteArrayList
Concurrency containerArrayList
。
Now let’s take a look at inheritanceCollection
Three sub interfaces of the interface.
List
List
Interface extended fromCollection
Interface, which is orderly and repeatable.
List
The following methods are added:
//Add set C to the set at a location
We often useList
Classes are mainlyArrayList
andLinkedList
。
ArrayList
ArrayList
Array is used to store objects in the bottom layer of
transient Object[] elementData;
And because of the realizationRandomAccess
Interface, so the search is very fast.
When adding an element, it is added at the endelementData[size++] = e
So adding in order is very fast.
andArrayList
When deleting elements, theSystem.arraycopy
Make a copy operation.
System.arraycopy(elementData, index+1, elementData, index, numMoved)
If you copy too many elements, you will lose performance.
LinkedList
LinkedList
The bottom layer of the system uses bidirectional linked list to store objects. Sequential access, allowing storage of any object (including null).LinkedList
It also realizes theDeque
Interface that is inherited fromQueue
So this class can be used as a queue.
public class LinkedList<E>
becauseLinkedList
RealizedDeque
Interface, so its operation is bidirectional. For example, in the following method, you can choose whether to add a header or a tail.
public void addFirst(E e) {
linkFirst(e);
}
public void addLast(E e) {
linkLast(e);
}
LinkedList
China and IsraelNode
Represents each node in the bidirectional linked list, as follows:
private static class Node<E> {
We know from the above source codeLinkedList
Data structure, therefore, to useLinkedList
When you add, delete, change and search, you will search from the beginningArrayList
It can be accessed randomly. However, when performing insert and delete operations, theArrayList
Fast, just point the pointer to the element you want.
Vector
Vector
Data structure and application ofArrayList
Similarly, both use arraysObject[] elementData
To store data, but will usesynchronized
Keyword lock synchronization:
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
add
The way is to usesynchronized
Keyword lock, others such asget
、remove
And other methods have lock. Therefore,Vector
usesynchronized
Keyword to ensure thread safety, but the efficiency is low, it is not recommended to use.
We generally recommend itArrayList
InsteadVector
To achieve the function.
Stack
Stack
Inherited fromVector
, which is a last in first out container, that is, constantly pushing elements in (push)Stack
The pop element must be the last one pressed inStack
Elements in.
Stack
There are several ways to realize it
//Type elements into the stack
But becauseStack
Inherited fromVector
So it also containsVector
All APIs in. So we don’t recommend it. We can use itDeque
Interface to realize the function of stack.
Thread safety
Because it’s thread safeVector
Class is not recommended, butArrayList
perhapsLinkedList
There is no thread safety mechanism. If we need to realize thread safety, we need to use itCollections
Static methods of classessynchronizedList()
Get thread safeList
Or useCopyOnWriteArrayList
Implementation of thread safe operation.
How to ensure that a set cannot be modified?
have access toCollections.unmodifiableCollection(Collection c)
Method to create a read-only collection so that any operation that changes the collection will be thrownjava.lang.UnsupportedOperationException
Abnormal.
Example code:
List<String> list = new ArrayList<>();
Queue
Queue
Queues are FIFO linear data structures; let’s take a lookQueue
Interface for:
public interface Queue<E> extends Collection<E> {
We can see from the above,Queue
Interfaces are inheritanceCollection
The sub interface of is mainly to add six methods, which can be divided into two groups for adding, deleting and querying.add/remove/element
For a group, its case is to throw an exception after failure;offer/poll/peek
For a group, its case is to return a special value (null or false) after failure. Only when the queue is bounded and there is no free space can the add operation throw an exception or returnfalse
. In this case, we useoffer
This is the way to replace itadd
This set of operations.
In JDK, there is no implementation of a queue, only oneQueue
Interface. becauseQueue
Only basic queue function. Therefore, we need to expandQueue
Interface.
PriorityQueue
PriorityQueue
It is a priority queue based on binary heap, which is implemented by array and can be specifiedComparator
Comparator, if not passed inComparator
Then the natural order is as follows:
public class PriorityQueue<E> extends AbstractQueue<E>
The above note describestransient Object[] queue
The stored priority queue is represented as a balanced binary tree, and the location of the queue and its sub queues. If you don’t pass incomparator
, will be sorted in natural order.
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)
grow(i + 1);
size = i + 1;
if (i == 0)
queue[0] = e;
else
siftUp(i, e);
return true;
}
Let’s take a look at its method of adding elements,PriorityQueue
Not thread safe and not supportednull
. If you want thread safety, you can use thejava.util.concurrent.PriorityBlockingQueue
Class.
Deque
Deque
The interface is rightQueue
The expansion of,Deque
Is inherited fromQueue
To achieve both ends can be in and out of the two terminal queue. It has the right APIFirst
End andLast
The operation of the terminal,add/remove/get
Is a group of operations, will throw exception;offer/poll/peek
Is a set of operations that return values on failure.
public interface Deque<E> extends Queue<E> {
When using, please select the same group to use.
realizationDeque
The main features of the interface areArrayDeque
、LinkedList
、PriorityQueue
And other concurrent containersConcurrentLinkedDeque
、LinkedBlockingDeque
And so on.
Here we only introduceArrayDeque
andPriorityQueue
。LinkedList
It’s already mentioned above.
ArrayDeque
ArrayDeque
It’s implementationDeque
Interface, which inherits from theAbstractCollection
The bottom layer is based onCollection
The collection framework of interface implementation is as follows
public class ArrayDeque<E> extends AbstractCollection<E>
Let’s take a lookArrayDeque
RealizedaddFirst
method:
public void addFirst(E e) {
if (e == null)
throw new NullPointerException();
elements[head = (head - 1) & (elements.length - 1)] = e;
if (head == tail)
doubleCapacity();
}
fromaddFirst
As you can see, its operation is not thread safe and cannot be insertednull
And ifhead == tail
Then the capacity will be expanded.
andLinkedList
It’s also trueDeque
The inevitable conflict withArrayDeque
Compare.
ArrayDeque
The bottom layer is implemented by arrays, while the bottom layer is implemented by arraysLinkedList
The bottom layer is realized by circular linked list. The performance of linked list in addition and deletion method is higher than that of array structure, but the performance of query method array structure is higher than that of linked list structure. But the elements in the array are not moved, only added at the back, and the efficiency is not bad.
ArrayDeque
It can be used as a queue or as a stack. So we can use it insteadStack
Realize the stack function.
Set
Set
Interface extended fromCollection
Interface, which is characterized by non repetition.
public interface Set<E> extends Collection<E> {
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean retainAll(Collection<?> c);
boolean removeAll(Collection<?> c);
void clear();
boolean equals(Object o);
int hashCode();
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT);
}
}
fromSet
Interface andCollection
For comparison,Set
With andCollection
Exactly the same interface, no extra functionality.
Set
The common implementation classes of areHashSet
、LinkedHashSet
AndTreeSet
。
HashSet
fromHashSet
The source code can be seen, its underlying useHashMap
Ofkey
To store elements, the main feature is disorder.
public class HashSet<E>
And fromadd
According to the method,HashSet
Is thread safe determined byHashMap
It’s a decision, not a decisionHashMap
It’s not thread safe in itself, soHashSet
It’s also thread unsafe.
LinkedHashSet
LinkedHashSet
Self inheritanceHashSet
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
public LinkedHashSet() {
super(16, .75f, true);
}
}
It calls the parent classHashSet
The construction method of this paper is as follows
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
There are construction methods in the parent class,HashMap
ByLinkedHashMap
To achieve, andLinkedHashMap
The underlying use of isHashMap
+Bidirectional list to achieve, so that you can retain the order of insertion.LinkedHashSet
It’s not thread safe either.
TreeSet
TreeSet
The bottom layer is to useTreeMap
The data structure is array + red black tree, so the elements stored in it are ordered. You can customize the comparator or use the comparator to realize natural sorting.
public class TreeSet<E> extends AbstractSet<E>
If you need to customize the sort, use the following construction method to pass in aComparator
Comparator:
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
TreeSet
Can’t storenull
And it’s not thread safe. becauseTreeSet
No repetition and orderly features, can be usedTreeSet
Realize the function of school performance list.
class Student implements Comparable<Student> {
That’s right up thereCollection
Let’s have a general introduction to the collectionMap
。
Map
Map
It’s stored bykey-value
The mapping table of the object composed of,key
It is unique and we can use itkey
To find the correspondingvalue
。
Let’s take a lookMap
Definition of interface:
public interface Map<K,V> {
There are some ways to knowMap
Functions provided. And forMap
There are two different directions for the implementation of
AbstractMap
: using abstract classes to implementMap
Some of the general functions are basically realizedMap
We should inherit it, for exampleHashMap
。SortedMap
That’s rightMap
Interface, which defines theComparator
Object, which is sorted according to, for exampleTreeMap
。
Here are some of the most commonly used implementation classesHashMap
、TreeMap
、LinkedHashMap
andConcurrentHashMap
。
HashMap
HashMap
It’s the most common oneMap
And it doesAbstractMap
class
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
It works by calculationkey
Objecthash
It depends on the valueMap
The order of insertion cannot be guaranteed.
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
Before JDK 1.8, the bottom layer usesArray + single linked list
Implementation; use after JDK 1.8Array + single linked list + red black tree
realization. happenhash
In case of conflict,HashMap
The elements with the same mapping address will be connected into a linked list. When the length of the linked list is greater than 8 and the length of the array is greater than 64, the single linked list will be converted into a red black tree.
TreeMap
TreeMap
It has the function of sortingMap
And it doesNavigableMap
Interface:
public interface NavigableMap<K,V> extends SortedMap<K,V> {
andNavigableMap
Is inherited fromSortedMap
Interface, which can receive aComparator
Make a custom sort:
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
And if you don’tComparator
By default, thekey
Natural order, therefore,key
It’s about to come trueComparable
Interface, otherwise it will be thrown at runtimejava.lang.CassCastException
Abnormal.
TreeMap
The bottom layer is made ofArray + red black tree
To achieve the data structure, the entire data structure is maintained in an orderly state, and can not be insertednull
Key, but there can benull
Value.
Here is a small example:
class Student {
LinkedHashMap
LinkedHashMap
It’s inHashMap
On the basis of the two-way linked list, used to ensure the order of the elements.
public class LinkedHashMap<K,V>
Here’s a little example:
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
It can be seen that its output is consistent with the insertion order, and it is orderly.
IdentityHashMap
IdentityHashMap
Inherited fromAbstractMap
Abstract class and implementMap
Interface, which connects withHashMap
The inheritance class of is basically the same as the implementation interface.
public class IdentityHashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, java.io.Serializable, Cloneable
howeverIdentityHashMap
useObject[] table
Array to store elements, and can store duplicatekey
Because inIdentityHashMap
Is used initem == k
It takes the same reference to judge whether they are the same.
Let’s look at the following example:
IdentityHashMap<String, Integer> identityHashMap = new IdentityHashMap<>();
that is becausejan1
andjan2
All you want is the data in the constant poolJan
. If you use the following methods:
IdentityHashMap<String, Integer> identityHashMap = new IdentityHashMap<>();
This shows thatjan2
It’s pointing to the space in the heap,new
The string object that comes out. And if you useidentityHashMap.get(new String("Jan"))
To get the value, it will outputnull
The principle is also a new string object created in the heap.
IdentityHashMap
Yeshash
Storage, so it’s out of order and not thread safe.
WeakHashMap
WeakHashMap
Inherited fromAbstractMap
Abstract class and implementMap
Interface, which is also based onhash
RealizedMap
So it’s related toHashMap
Most of the functions of are the same.
public class WeakHashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>
But inWeakHashMap
Implemented inEntry
But not the same:
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry <K,V> {
Entry
InheritedWeakReference
, usingWeakReference
Does not prevent GC recoveryKey
That is, every GC will clear this object.
andWeakHashMap
Maintenance inReferenceQueue
What is the purpose of storagekey
Has been cleared.
private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
Every timeput/size
And so onexpungeStaleEntries
Method to delete the deleted data in the tablekey
CorrespondingEntry
To achieve the effect of synchronization.
private void expungeStaleEntries() {
WeakHashMap
It is usually used as a cache to store key value pairs that only need to be saved for a short time. It is also a non thread safe collection.
Hashtable
Hashtable
It’s also trueMap
Interface. Underlying useArray + linked list
To achieve.
public class Hashtable<K,V>
In progressput/remove
And so onsynchronized
Keyword to achieve synchronization, relatively simple.
public synchronized V put(K key, V value) {
if (value == null) {
throw new NullPointerException();
}
Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
addEntry(hash, key, value, index);
return null;
}
This kind of operation makesHashtable
Is a thread safeMap
But it also makes theHashtable
The performance of the system is poorVector
Almost, so it’s going to be eliminated.
And we want to use thread safeMap
, you can usejava.util.concurrent
Under the bagConcurrentHashMap
Class.
summary
This article is to do a more overall introduction to Java container, to understand the characteristics of each container. Let’s summarize:
- Stored as an object, using the implementation
Collection
Interface implementation class; stored by key value pair, using implementationMap
Interface implementation class. - realization
List
The classes of the interface are all ordered and repeatable collectionsArrayList
、LinkedList
andVector
。 - realization
Set
The elements stored in the classes of the interface are not repeatableHashSet
、LinkedHashSet
andTreeSet
。 Queue
Interface implements the basic operation of the queue, andDeque
Defines the operation of a two terminal queue.- Realized
Map
Interface classes are based onhash
StoredHashMap
That can be sortedTreeMap
And weakly quotedWeakHashMap
。
When selecting containers, we usually compare their data structure, thread safety, repetition, order and application scenarios to select the containers we want to use.
More content, please pay attention to the official account.Hairen’s blog“, reply to” resources “to get free learning resources!