From 89b27f25c9722886dedb957cf9a2138e4b170821 Mon Sep 17 00:00:00 2001 From: yuchenCD <35260837+yuchenCD@users.noreply.github.com> Date: Fri, 6 Mar 2020 18:06:09 +0800 Subject: [PATCH 1/4] init --- second/week_01/75/075-ArrayList.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 second/week_01/75/075-ArrayList.md diff --git a/second/week_01/75/075-ArrayList.md b/second/week_01/75/075-ArrayList.md new file mode 100644 index 0000000..8175072 --- /dev/null +++ b/second/week_01/75/075-ArrayList.md @@ -0,0 +1,17 @@ +## ArrayList ## +### introduce ### +``ArrayList是List接口的可变容量数组实现。实现了List接口的所有可选方法,并且支持所有元素,包括null。 +除此之外,ArrayList还提供了方法用来改变储存元素的数组的容量。ArrayList除了不同步,大致等同于Vector。`` + +``size(),isEmpty(),get(),set(),iterator(),listIterator()方法执行耗时是恒等的。 +add()方法时间复杂度为O(n)。其他方法时间复杂度大致为O(n),且常量因子比LinkedList对应的实现要小。`` + +``每个ArrayList对象都有capacity属性,指用于储存元素的数组的容量。capacity总是大于等于集合的大小。 +当有元素被加入到ArrayList中时,capacity自动增大,增大策略的细节不可见。`` + +``在添加大量元素前使用ensureCapacity()方法扩容ArrayList对象,以减少自动扩容的次数。`` + +``注意:ArrayList是不同步的。如果多个线程同时操作一个ArrayList对象,并且其中一个线程有结构性修改操作 +(结构性修改包括增加/删除元素或修改数组大小,不包括修改某个元素的属性值),必须做同步处理。通常通过对集合 +的封装类进行同步来实现,或使用Collections.synchronizedList()方法。`` + -- Gitee From 2e55c09abde40805aced35444551ef463469d051 Mon Sep 17 00:00:00 2001 From: yuchen Date: Sat, 7 Mar 2020 19:40:22 +0800 Subject: [PATCH 2/4] =?UTF-8?q?059=5Fweek06=5F=E5=A2=9E=E5=BC=BA=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=8F=8A=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- second/week_01/75/075-ArrayList.md | 190 ++++++++++++++++++++++++++++- 1 file changed, 185 insertions(+), 5 deletions(-) diff --git a/second/week_01/75/075-ArrayList.md b/second/week_01/75/075-ArrayList.md index 8175072..fd9b39e 100644 --- a/second/week_01/75/075-ArrayList.md +++ b/second/week_01/75/075-ArrayList.md @@ -1,17 +1,197 @@ ## ArrayList ## -### introduce ### +### Introduce ### +```java + * Resizable-array implementation of the List interface. Implements + * all optional list operations, and permits all elements, including + * null. In addition to implementing the List interface, + * this class provides methods to manipulate the size of the array that is + * used internally to store the list. (This class is roughly equivalent to + * Vector, except that it is unsynchronized.) +``` ``ArrayList是List接口的可变容量数组实现。实现了List接口的所有可选方法,并且支持所有元素,包括null。 除此之外,ArrayList还提供了方法用来改变储存元素的数组的容量。ArrayList除了不同步,大致等同于Vector。`` - +```java +

The size, isEmpty, get, set, + * iterator, and listIterator operations run in constant + * time. The add operation runs in amortized constant time, + * that is, adding n elements requires O(n) time. All of the other operations + * run in linear time (roughly speaking). The constant factor is low compared + * to that for the LinkedList implementation. +``` ``size(),isEmpty(),get(),set(),iterator(),listIterator()方法执行耗时是恒等的。 add()方法时间复杂度为O(n)。其他方法时间复杂度大致为O(n),且常量因子比LinkedList对应的实现要小。`` - +```java +

Each ArrayList instance has a capacity. The capacity is + * the size of the array used to store the elements in the list. It is always + * at least as large as the list size. As elements are added to an ArrayList, + * its capacity grows automatically. The details of the growth policy are not + * specified beyond the fact that adding an element has constant amortized + * time cost. +``` ``每个ArrayList对象都有capacity属性,指用于储存元素的数组的容量。capacity总是大于等于集合的大小。 当有元素被加入到ArrayList中时,capacity自动增大,增大策略的细节不可见。`` - +```java +*

An application can increase the capacity of an ArrayList instance + * before adding a large number of elements using the ensureCapacity + * operation. This may reduce the amount of incremental reallocation. +``` ``在添加大量元素前使用ensureCapacity()方法扩容ArrayList对象,以减少自动扩容的次数。`` - +```java + *

Note that this implementation is not synchronized. + * If multiple threads access an ArrayList instance concurrently, + * and at least one of the threads modifies the list structurally, it + * must be synchronized externally. (A structural modification is + * any operation that adds or deletes one or more elements, or explicitly + * resizes the backing array; merely setting the value of an element is not + * a structural modification.) This is typically accomplished by + * synchronizing on some object that naturally encapsulates the list. +``` ``注意:ArrayList是不同步的。如果多个线程同时操作一个ArrayList对象,并且其中一个线程有结构性修改操作 (结构性修改包括增加/删除元素或修改数组大小,不包括修改某个元素的属性值),必须做同步处理。通常通过对集合 的封装类进行同步来实现,或使用Collections.synchronizedList()方法。`` +```java + *

+ * The iterators returned by this class's {@link #iterator() iterator} and + * {@link #listIterator(int) listIterator} methods are fail-fast: + * if the list is structurally modified at any time after the iterator is + * created, in any way except through the iterator's own + * {@link ListIterator#remove() remove} or + * {@link ListIterator#add(Object) add} methods, the iterator will throw a + * {@link ConcurrentModificationException}. Thus, in the face of + * concurrent modification, the iterator fails quickly and cleanly, rather + * than risking arbitrary, non-deterministic behavior at an undetermined + * time in the future. + *

Note that the fail-fast behavior of an iterator cannot be guaranteed + * as it is, generally speaking, impossible to make any hard guarantees in the + * presence of unsynchronized concurrent modification. Fail-fast iterators + * throw {@code ConcurrentModificationException} on a best-effort basis. + * Therefore, it would be wrong to write a program that depended on this + * exception for its correctness: the fail-fast behavior of iterators + * should be used only to detect bugs. +``` +``由iterator()及listIterator(int)方法返回的迭代器有快速失败机制:除了迭代器本身的remove()和add()方法, +集合一旦被其他任何线程结构性的修改,都会抛出ConcurrentModificationException. +迭代器的快速失败行为是不一定能够得到保证的,一般来说,存在非同步的并发修改时,不可能做出任何坚决的保证的。 +但是快速失败迭代器会做出最大的努力来抛出ConcurrentModificationException。因此,编写依赖于此异常的程序的做法是不正确的。 +正确的做法应该是:迭代器的快速失败行为应该仅用于检测程序中的bug。`` + +### Structures + +```java +/** + * Constructs an empty list with an initial capacity of ten. + * 无参构造方法,使用默认初始容量10 + */ + + public ArrayList() { + this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; + } + +``` + + +```java +/** + * Constructs an empty list with the specified initial capacity. + * @param initialCapacity the initial capacity of the list + * @throws IllegalArgumentException if the specified initial capacity + * is negative + * 指定初始容量的构造方法,参数initialCapacity必须大于等于0, + 否则抛出IllegalArgumentException。 + */ + public ArrayList(int initialCapacity) { + if (initialCapacity > 0) { + this.elementData = new Object[initialCapacity]; + } else if (initialCapacity == 0) { + //当initialCapacity=0时,属性elementData=类共享空数组EMPTY_ELEMENTDATA + this.elementData = EMPTY_ELEMENTDATA; + } else { + throw new IllegalArgumentException("Illegal Capacity: "+ + initialCapacity); + } + } +``` + +```java +/** + * Constructs a list containing the elements of the specified + * collection, in the order they are returned by the collection's + * iterator. + * + * @param c the collection whose elements are to be placed into this list + * @throws NullPointerException if the specified collection is null + * 指定元素集合的构造方法,元素顺序由该集合的迭代顺序决定。 + */ + public ArrayList(Collection c) { + elementData = c.toArray(); + if ((size = elementData.length) != 0) { + if (elementData.getClass() != Object[].class) + elementData = Arrays.copyOf(elementData, size, Object[].class); + } else { + // 当元素数量为0时,属性elementData=类共享空数组EMPTY_ELEMENTDATA + this.elementData = EMPTY_ELEMENTDATA; + } + } +``` + + ### 重要methods ### + + ```java +/** + * Trims the capacity of this ArrayList instance to be the + * list's current size. An application can use this operation to minimize + * the storage of an ArrayList instance. + * 使ArrayList对象的数组长度等于元素数量,减少ArrayList占用的储存空间。 + */ + public void trimToSize() { + //操作次数++ + modCount++; + if (size < elementData.length) { + elementData = (size == 0) + ? EMPTY_ELEMENTDATA + : Arrays.copyOf(elementData, size); + } + } +``` +```java +/** + * Increases the capacity of this ArrayList instance, if + * necessary, to ensure that it can hold at least the number of elements + * specified by the minimum capacity argument. + * + * @param minCapacity the desired minimum capacity + * 扩大集合的容量至minCapacity, + */ + public void ensureCapacity(int minCapacity) { + int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) + ? 0 + : DEFAULT_CAPACITY; + + if (minCapacity > minExpand) { + ensureExplicitCapacity(minCapacity); + } + } + + private void ensureExplicitCapacity(int minCapacity) { + modCount++; + + // overflow-conscious code + if (minCapacity - elementData.length > 0) + grow(minCapacity); + } + + private void grow(int minCapacity) { + int oldCapacity = elementData.length; + int newCapacity = oldCapacity + (oldCapacity >> 1); + //如果minCapacity小于原容量的3/2,则扩容至原容量的3/2; + if (newCapacity - minCapacity < 0) + newCapacity = minCapacity; + //如果minCapacity大于数组最大长度(Interger的MAX_VALUE - 8),则扩容至Interger的MAX_VALUE - 8 + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(minCapacity); + elementData = Arrays.copyOf(elementData, newCapacity); + } +``` +```java +``` \ No newline at end of file -- Gitee From cf25d0035cb4ae24479fd4b8c8d20114e9ee9f0d Mon Sep 17 00:00:00 2001 From: yuchen Date: Sat, 7 Mar 2020 19:43:43 +0800 Subject: [PATCH 3/4] arrayList --- second/week_01/75/075-ArrayList.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/second/week_01/75/075-ArrayList.md b/second/week_01/75/075-ArrayList.md index fd9b39e..07d4ada 100644 --- a/second/week_01/75/075-ArrayList.md +++ b/second/week_01/75/075-ArrayList.md @@ -1,43 +1,49 @@ ## ArrayList ## ### Introduce ### ```java +/* * Resizable-array implementation of the List interface. Implements * all optional list operations, and permits all elements, including * null. In addition to implementing the List interface, * this class provides methods to manipulate the size of the array that is * used internally to store the list. (This class is roughly equivalent to * Vector, except that it is unsynchronized.) + * / ``` ``ArrayList是List接口的可变容量数组实现。实现了List接口的所有可选方法,并且支持所有元素,包括null。 除此之外,ArrayList还提供了方法用来改变储存元素的数组的容量。ArrayList除了不同步,大致等同于Vector。`` ```java -

The size, isEmpty, get, set, +/* + *

The size, isEmpty, get, set, * iterator, and listIterator operations run in constant * time. The add operation runs in amortized constant time, * that is, adding n elements requires O(n) time. All of the other operations * run in linear time (roughly speaking). The constant factor is low compared * to that for the LinkedList implementation. + * / ``` ``size(),isEmpty(),get(),set(),iterator(),listIterator()方法执行耗时是恒等的。 add()方法时间复杂度为O(n)。其他方法时间复杂度大致为O(n),且常量因子比LinkedList对应的实现要小。`` ```java -

Each ArrayList instance has a capacity. The capacity is +/*

Each ArrayList instance has a capacity. The capacity is * the size of the array used to store the elements in the list. It is always * at least as large as the list size. As elements are added to an ArrayList, * its capacity grows automatically. The details of the growth policy are not * specified beyond the fact that adding an element has constant amortized * time cost. + * / ``` ``每个ArrayList对象都有capacity属性,指用于储存元素的数组的容量。capacity总是大于等于集合的大小。 当有元素被加入到ArrayList中时,capacity自动增大,增大策略的细节不可见。`` ```java -*

An application can increase the capacity of an ArrayList instance +/*

An application can increase the capacity of an ArrayList instance * before adding a large number of elements using the ensureCapacity * operation. This may reduce the amount of incremental reallocation. + * / ``` ``在添加大量元素前使用ensureCapacity()方法扩容ArrayList对象,以减少自动扩容的次数。`` ```java - *

Note that this implementation is not synchronized. + /*

Note that this implementation is not synchronized. * If multiple threads access an ArrayList instance concurrently, * and at least one of the threads modifies the list structurally, it * must be synchronized externally. (A structural modification is @@ -45,12 +51,13 @@ add()方法时间复杂度为O(n)。其他方法时间复杂度大致为O(n),且 * resizes the backing array; merely setting the value of an element is not * a structural modification.) This is typically accomplished by * synchronizing on some object that naturally encapsulates the list. + * / ``` ``注意:ArrayList是不同步的。如果多个线程同时操作一个ArrayList对象,并且其中一个线程有结构性修改操作 (结构性修改包括增加/删除元素或修改数组大小,不包括修改某个元素的属性值),必须做同步处理。通常通过对集合 的封装类进行同步来实现,或使用Collections.synchronizedList()方法。`` ```java - *

+/*

* The iterators returned by this class's {@link #iterator() iterator} and * {@link #listIterator(int) listIterator} methods are fail-fast: * if the list is structurally modified at any time after the iterator is @@ -68,6 +75,7 @@ add()方法时间复杂度为O(n)。其他方法时间复杂度大致为O(n),且 * Therefore, it would be wrong to write a program that depended on this * exception for its correctness: the fail-fast behavior of iterators * should be used only to detect bugs. + */ ``` ``由iterator()及listIterator(int)方法返回的迭代器有快速失败机制:除了迭代器本身的remove()和add()方法, 集合一旦被其他任何线程结构性的修改,都会抛出ConcurrentModificationException. -- Gitee From 4aeb899c8b37df6469a1e979f21e6f82446fea4b Mon Sep 17 00:00:00 2001 From: yuchen Date: Sun, 8 Mar 2020 00:23:59 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E5=91=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- second/week_01/75/075-ArrayList.md | 13 +- second/week_01/75/075-HashMap.md | 293 ++++++++++++++++++++++++++++ second/week_01/75/075-LinkedList.md | 208 ++++++++++++++++++++ 3 files changed, 508 insertions(+), 6 deletions(-) create mode 100644 second/week_01/75/075-HashMap.md create mode 100644 second/week_01/75/075-LinkedList.md diff --git a/second/week_01/75/075-ArrayList.md b/second/week_01/75/075-ArrayList.md index 07d4ada..f9987d8 100644 --- a/second/week_01/75/075-ArrayList.md +++ b/second/week_01/75/075-ArrayList.md @@ -1,7 +1,7 @@ ## ArrayList ## ### Introduce ### ```java -/* +/** * Resizable-array implementation of the List interface. Implements * all optional list operations, and permits all elements, including * null. In addition to implementing the List interface, @@ -13,7 +13,7 @@ ``ArrayList是List接口的可变容量数组实现。实现了List接口的所有可选方法,并且支持所有元素,包括null。 除此之外,ArrayList还提供了方法用来改变储存元素的数组的容量。ArrayList除了不同步,大致等同于Vector。`` ```java -/* +/** *

The size, isEmpty, get, set, * iterator, and listIterator operations run in constant * time. The add operation runs in amortized constant time, @@ -25,7 +25,8 @@ ``size(),isEmpty(),get(),set(),iterator(),listIterator()方法执行耗时是恒等的。 add()方法时间复杂度为O(n)。其他方法时间复杂度大致为O(n),且常量因子比LinkedList对应的实现要小。`` ```java -/*

Each ArrayList instance has a capacity. The capacity is +/** + *

Each ArrayList instance has a capacity. The capacity is * the size of the array used to store the elements in the list. It is always * at least as large as the list size. As elements are added to an ArrayList, * its capacity grows automatically. The details of the growth policy are not @@ -36,14 +37,14 @@ add()方法时间复杂度为O(n)。其他方法时间复杂度大致为O(n),且 ``每个ArrayList对象都有capacity属性,指用于储存元素的数组的容量。capacity总是大于等于集合的大小。 当有元素被加入到ArrayList中时,capacity自动增大,增大策略的细节不可见。`` ```java -/*

An application can increase the capacity of an ArrayList instance +/**

An application can increase the capacity of an ArrayList instance * before adding a large number of elements using the ensureCapacity * operation. This may reduce the amount of incremental reallocation. * / ``` ``在添加大量元素前使用ensureCapacity()方法扩容ArrayList对象,以减少自动扩容的次数。`` ```java - /*

Note that this implementation is not synchronized. + /**

Note that this implementation is not synchronized. * If multiple threads access an ArrayList instance concurrently, * and at least one of the threads modifies the list structurally, it * must be synchronized externally. (A structural modification is @@ -57,7 +58,7 @@ add()方法时间复杂度为O(n)。其他方法时间复杂度大致为O(n),且 (结构性修改包括增加/删除元素或修改数组大小,不包括修改某个元素的属性值),必须做同步处理。通常通过对集合 的封装类进行同步来实现,或使用Collections.synchronizedList()方法。`` ```java -/*

+/**

* The iterators returned by this class's {@link #iterator() iterator} and * {@link #listIterator(int) listIterator} methods are fail-fast: * if the list is structurally modified at any time after the iterator is diff --git a/second/week_01/75/075-HashMap.md b/second/week_01/75/075-HashMap.md new file mode 100644 index 0000000..775977d --- /dev/null +++ b/second/week_01/75/075-HashMap.md @@ -0,0 +1,293 @@ +## HashMap ## +### Introduce ### +```java +/** + * Hash table based implementation of the Map interface. This + * implementation provides all of the optional map operations, and permits + * null values and the null key. (The HashMap + * class is roughly equivalent to Hashtable, except that it is + * unsynchronized and permits nulls.) This class makes no guarantees as to + * the order of the map; in particular, it does not guarantee that the order + * will remain constant over time. + * / +``` +`` +HashMap是基于hash table表的Map接口实现。实现了Map接口的所有可选方法,并且允许null值和null键。 +HashMap除了不同步和允许空值,大致等同于HashTable。 +HashMap中的映射是无序的。 +`` +```java +/** + *

This implementation provides constant-time performance for the basic + * operations (get and put), assuming the hash function + * disperses the elements properly among the buckets. Iteration over + * collection views requires time proportional to the "capacity" of the + * HashMap instance (the number of buckets) plus its size (the number + * of key-value mappings). Thus, it's very important not to set the initial + * capacity too high (or the load factor too low) if iteration performance is + * important. + */ + ``` + `` + HashMap提供了恒等时间的get/put操作,前提是元素均匀得分布在hash桶中。 + `` + `` + HashMap根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。 + HashMap最多只允许一条记录的键为null,允许多条记录的值为null。HashMap非线程安全,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。 + 如果需要满足线程安全,可以用 Collections的synchronizedMap方法使HashMap具有线程安全的能力,或者使用ConcurrentHashMap + `` + +### 关键属性 ### + ```java + /** + * The default initial capacity - MUST be a power of two. + * 默认的初始化容量 16; + * 容量取2的平方是为了在resize时,hash重新分配更方便 h&(length - 1) == h % length + */ + static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 + + /** + * The maximum capacity, used if a higher value is implicitly specified + * by either of the constructors with arguments. + * MUST be a power of two <= 1<<30. + */ + static final int MAXIMUM_CAPACITY = 1 << 30; + + /** + * The load factor used when none specified in constructor. + * 在数组定义好长度之后,负载因子越大,所能容纳的键值对个数越多。 + * threshold = capacity * Load factor + * 默认的负载因子0.75是对空间和时间效率的一个平衡选择,建议不要修改,除非在时间和空间比较特殊的情况下,比如内存空间很多而又对时间效率要求很高,可以降低负载因子Load factor的值;相反,如果内存空间紧张而对时间效率要求不高,可以增加负载因子loadFactor的值,这个值可以大于1 + */ + static final float DEFAULT_LOAD_FACTOR = 0.75f; + + /** + * The bin count threshold for using a tree rather than list for a + * bin. Bins are converted to trees when adding an element to a + * bin with at least this many nodes. The value must be greater + * than 2 and should be at least 8 to mesh with assumptions in + * tree removal about conversion back to plain bins upon + * shrinkage. + * 扩容阈值 + * 当键值对数量 >= 8 时,将链表转换为红黑树 + */ + static final int TREEIFY_THRESHOLD = 8; + + /** + * The bin count threshold for untreeifying a (split) bin during a + * resize operation. Should be less than TREEIFY_THRESHOLD, and at + * most 6 to mesh with shrinkage detection under removal. + * 当键值对数量 <= 6 时,将红黑树转换为链表 + */ + static final int UNTREEIFY_THRESHOLD = 6; + + /** + * The smallest table capacity for which bins may be treeified. + * (Otherwise the table is resized if too many nodes in a bin.) + * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts + * between resizing and treeification thresholds. + * 如果Node数组的长度小于64,则不会将链表转换为红黑树 + */ + static final int MIN_TREEIFY_CAPACITY = 64; + + /** + * The table, initialized on first use, and resized as + * necessary. When allocated, length is always a power of two. + * (We also tolerate length zero in some operations to allow + * bootstrapping mechanics that are currently not needed.) + * Node数组 + */ + transient Node[] table; + ``` + + ### 构造方法 ### + ```java + /** + * Constructs an empty HashMap with the specified initial + * capacity and load factor. + * + * @param initialCapacity the initial capacity + * @param loadFactor the load factor + * @throws IllegalArgumentException if the initial capacity is negative + * or the load factor is nonpositive + * 设置初始容量和负载因子 + */ + public HashMap(int initialCapacity, float loadFactor) { + if (initialCapacity < 0) + throw new IllegalArgumentException("Illegal initial capacity: " + + initialCapacity); + if (initialCapacity > MAXIMUM_CAPACITY) + initialCapacity = MAXIMUM_CAPACITY; + if (loadFactor <= 0 || Float.isNaN(loadFactor)) + throw new IllegalArgumentException("Illegal load factor: " + + loadFactor); + this.loadFactor = loadFactor; + this.threshold = tableSizeFor(initialCapacity); + } + /** + * Constructs an empty HashMap with the specified initial + * capacity and the default load factor (0.75). + * + * @param initialCapacity the initial capacity. + * @throws IllegalArgumentException if the initial capacity is negative. + * 设置初始容量 + */ + public HashMap(int initialCapacity) { + this(initialCapacity, DEFAULT_LOAD_FACTOR); + } + + /** + * Constructs an empty HashMap with the default initial capacity + * (16) and the default load factor (0.75). + * 无参构造 + */ + public HashMap() { + this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted + } + + /** + * Constructs a new HashMap with the same mappings as the + * specified Map. The HashMap is created with + * default load factor (0.75) and an initial capacity sufficient to + * hold the mappings in the specified Map. + * + * @param m the map whose mappings are to be placed in this map + * @throws NullPointerException if the specified map is null + * + */ + public HashMap(Map m) { + this.loadFactor = DEFAULT_LOAD_FACTOR; + putMapEntries(m, false); + } + ``` + + ### 重要方法 + + ```java + /** + * Returns the value to which the specified key is mapped, + * or {@code null} if this map contains no mapping for the key. + * + *

More formally, if this map contains a mapping from a key + * {@code k} to a value {@code v} such that {@code (key==null ? k==null : + * key.equals(k))}, then this method returns {@code v}; otherwise + * it returns {@code null}. (There can be at most one such mapping.) + * + *

A return value of {@code null} does not necessarily + * indicate that the map contains no mapping for the key; it's also + * possible that the map explicitly maps the key to {@code null}. + * The {@link #containsKey containsKey} operation may be used to + * distinguish these two cases. + * + * @see #put(Object, Object) + * 根据key获取 + */ + public V get(Object key) { + Node e; + return (e = getNode(hash(key), key)) == null ? null : e.value; + } + + /** + * Implements Map.get and related methods. + * + * @param hash hash for key + * @param key the key + * @return the node, or null if none + */ + final Node getNode(int hash, Object key) { + Node[] tab; Node first, e; int n; K k; + if ((tab = table) != null && (n = tab.length) > 0 && + (first = tab[(n - 1) & hash]) != null) { + if (first.hash == hash && // always check first node + ((k = first.key) == key || (key != null && key.equals(k)))) + return first; + if ((e = first.next) != null) { + if (first instanceof TreeNode) + //红黑树 + return ((TreeNode)first).getTreeNode(hash, key); + //从头遍历整个链表 + do { + if (e.hash == hash && + ((k = e.key) == key || (key != null && key.equals(k)))) + return e; + } while ((e = e.next) != null); + } + } + return null; + } + ``` + +```java +/** + * Associates the specified value with the specified key in this map. + * If the map previously contained a mapping for the key, the old + * value is replaced. + * + * @param key key with which the specified value is to be associated + * @param value value to be associated with the specified key + * @return the previous value associated with key, or + * null if there was no mapping for key. + * (A null return can also indicate that the map + * previously associated null with key.) + */ + public V put(K key, V value) { + return putVal(hash(key), key, value, false, true); + } + + /** + * Implements Map.put and related methods. + * + * @param hash hash for key + * @param key the key + * @param value the value to put + * @param onlyIfAbsent if true, don't change existing value + * @param evict if false, the table is in creation mode. + * @return previous value, or null if none + */ + final V putVal(int hash, K key, V value, boolean onlyIfAbsent, + boolean evict) { + Node[] tab; Node p; int n, i; + if ((tab = table) == null || (n = tab.length) == 0) + n = (tab = resize()).length; + if ((p = tab[i = (n - 1) & hash]) == null) + tab[i] = newNode(hash, key, value, null); + else { + Node e; K k; + if (p.hash == hash && + ((k = p.key) == key || (key != null && key.equals(k)))) + e = p; + else if (p instanceof TreeNode) + e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value); + else { + for (int binCount = 0; ; ++binCount) { + if ((e = p.next) == null) { + p.next = newNode(hash, key, value, null); + if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st + //转换为红黑树 + treeifyBin(tab, hash); + break; + } + if (e.hash == hash && + ((k = e.key) == key || (key != null && key.equals(k)))) + break; + p = e; + } + } + //替换已有键值 + if (e != null) { // existing mapping for key + V oldValue = e.value; + if (!onlyIfAbsent || oldValue == null) + e.value = value; + afterNodeAccess(e); + return oldValue; + } + } + ++modCount; + //扩容 + if (++size > threshold) + resize(); + afterNodeInsertion(evict); + return null; + } +``` + diff --git a/second/week_01/75/075-LinkedList.md b/second/week_01/75/075-LinkedList.md new file mode 100644 index 0000000..520d59f --- /dev/null +++ b/second/week_01/75/075-LinkedList.md @@ -0,0 +1,208 @@ +## LinkedList +`` +ArrayList和LinkedList是List接口的两种不同的实现,ArrayList的增删效率低,但是改查效率高。 +而LinkedList正好相反,增删由于不需要移动底层数组数据,其底层是链表实现的,只需要修改链表节点指针,所以效率较高。 +而改和查,都需要先定位到目标节点,所以效率较低。 +概括的说,LinkedList 是线程不安全的,允许元素为null的双向链表。 +其底层数据结构是链表,它实现List, Deque, Cloneable, java.io.Serializable接口,它实现了Deque,所以它也可以作为一个双端队列。和ArrayList比,没有实现RandomAccess所以其以下标,随机访问元素速度较慢。 +因其底层数据结构是链表,所以可想而知,它的增删只需要移动指针即可,故时间效率较高。不需要批量扩容,也不需要预留空间,所以空间效率比ArrayList高。 +缺点就是需要随机访问元素时,时间效率很低,虽然底层在根据下标查询Node的时候,会根据index判断目标Node在前半段还是后半段,然后决定是顺序还是逆序查询,以提升时间效率。不过随着n的增大,总体时间效率依然很低。 +当每次增、删时,都会修改modCount。 +`` +### 构造方法 ### +```java +/** + * Constructs an empty list. + * 无参构造 + */ + public LinkedList() { + } + + /** + * Constructs a list containing the elements of the specified + * collection, in the order they are returned by the collection's + * iterator. + * + * @param c the collection whose elements are to be placed into this list + * @throws NullPointerException if the specified collection is null + */ + public LinkedList(Collection c) { + this(); + //adAll继承自List接口,当批量添加时,c会先转化为数组进行for循环添加 + addAll(c); + } +``` +### 重要属性 ### +```java + //集合中的元素总数 + transient int size = 0; + + /** + * Pointer to first node. + * Invariant: (first == null && last == null) || + * (first.prev == null && first.item != null) + * 双向链表的第一个元素 + */ + transient Node first; + + /** + * Pointer to last node. + * Invariant: (first == null && last == null) || + * (last.next == null && last.item != null) + * 双向链表的最后一个元素 + */ + transient Node last; + + //双向链表结点内部类 + private static class Node { + E item; + Node next; + Node prev; + + Node(Node prev, E element, Node next) { + this.item = element; + this.next = next; + this.prev = prev; + } + } +``` +### 重要方法 ### +```java +/** + * Appends the specified element to the end of this list. + * + *

This method is equivalent to {@link #addLast}. + * + * @param e element to be appended to this list + * @return {@code true} (as specified by {@link Collection#add}) + */ + public boolean add(E e) { + //默认添加至链表尾部 + linkLast(e); + return true; + } +``` +```java +/** + * Removes the first occurrence of the specified element from this list, + * if it is present. If this list does not contain the element, it is + * unchanged. More formally, removes the element with the lowest index + * {@code i} such that + * (o==null ? get(i)==null : o.equals(get(i))) + * (if such an element exists). Returns {@code true} if this list + * contained the specified element (or equivalently, if this list + * changed as a result of the call). + * + * @param o element to be removed from this list, if present + * @return {@code true} if this list contained the specified element + */ + public boolean remove(Object o) { + //删除空节点 + if (o == null) { + for (Node x = first; x != null; x = x.next) { + if (x.item == null) { + unlink(x); + return true; + } + } + //非空节点 + } else { + for (Node x = first; x != null; x = x.next) { + if (o.equals(x.item)) { + unlink(x); + return true; + } + } + } + return false; + } + + /** + * Unlinks non-null node x. + * unlink方法通过操作节点的next和prev属性,实现快速删除 + */ + E unlink(Node x) { + // assert x != null; + final E element = x.item; + final Node next = x.next; + final Node prev = x.prev; + + if (prev == null) { + first = next; + } else { + prev.next = next; + x.prev = null; + } + + if (next == null) { + last = prev; + } else { + next.prev = prev; + x.next = null; + } + + x.item = null; + size--; + modCount++; + return element; + } +``` +```java + /** + * Retrieves, but does not remove, the first element of this list, + * or returns {@code null} if this list is empty. + * + * @return the first element of this list, or {@code null} + * if this list is empty + * @since 1.6 + * peek会取出当前第一个元素,但不从集合中删除 + */ + public E peekFirst() { + final Node f = first; + return (f == null) ? null : f.item; + } + + /** + * Retrieves and removes the first element of this list, + * or returns {@code null} if this list is empty. + * + * @return the first element of this list, or {@code null} if + * this list is empty + * @since 1.6 + * pool会取出当前第一个元素并从集合中删除 + */ + public E pollFirst() { + final Node f = first; + return (f == null) ? null : unlinkFirst(f); + } + + /** + * Pushes an element onto the stack represented by this list. In other + * words, inserts the element at the front of this list. + * + *

This method is equivalent to {@link #addFirst}. + * + * @param e the element to push + * @since 1.6 + * 等同与addFirst() + */ + public void push(E e) { + addFirst(e); + } + + /** + * Pops an element from the stack represented by this list. In other + * words, removes and returns the first element of this list. + * + *

This method is equivalent to {@link #removeFirst()}. + * + * @return the element at the front of this list (which is the top + * of the stack represented by this list) + * @throws NoSuchElementException if this list is empty + * @since 1.6 + * 等同与removeFirst() + */ + public E pop() { + return removeFirst(); + } +``` \ No newline at end of file -- Gitee