zoukankan      html  css  js  c++  java
  • ArrayList

    1. /* 
    2.  * @(#)ArrayList.java   1.56 06/04/21 
    3.  * 
    4.  * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 
    5.  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 
    6.  */  
    7. package java.util;  
    8. /** 
    9.  * Resizable-array implementation of the <tt>List</tt> interface.  Implements 
    10.  * all optional list operations, and permits all elements, including 
    11.  * <tt>null</tt>.  In addition to implementing the <tt>List</tt> interface, 
    12.  * this class provides methods to manipulate the size of the array that is 
    13.  * used internally to store the list.  (This class is roughly equivalent to 
    14.  * <tt>Vector</tt>, except that it is unsynchronized.)<p> 
    15.  * 
    16.  * The <tt>size</tt>, <tt>isEmpty</tt>, <tt>get</tt>, <tt>set</tt>, 
    17.  * <tt>iterator</tt>, and <tt>listIterator</tt> operations run in constant 
    18.  * time.  The <tt>add</tt> operation runs in <i>amortized constant time</i>, 
    19.  * that is, adding n elements requires O(n) time.  All of the other operations 
    20.  * run in linear time (roughly speaking).  The constant factor is low compared 
    21.  * to that for the <tt>LinkedList</tt> implementation.<p> 
    22.  * 
    23.  * Each <tt>ArrayList</tt> instance has a <i>capacity</i>.  The capacity is 
    24.  * the size of the array used to store the elements in the list.  It is always 
    25.  * at least as large as the list size.  As elements are added to an ArrayList, 
    26.  * its capacity grows automatically.  The details of the growth policy are not 
    27.  * specified beyond the fact that adding an element has constant amortized 
    28.  * time cost.<p> 
    29.  * 
    30.  * An application can increase the capacity of an <tt>ArrayList</tt> instance 
    31.  * before adding a large number of elements using the <tt>ensureCapacity</tt> 
    32.  * operation.  This may reduce the amount of incremental reallocation. 
    33.  * 
    34.  * <p><strong>Note that this implementation is not synchronized.</strong> 
    35.  * If multiple threads access an <tt>ArrayList</tt> instance concurrently, 
    36.  * and at least one of the threads modifies the list structurally, it 
    37.  * <i>must</i> be synchronized externally.  (A structural modification is 
    38.  * any operation that adds or deletes one or more elements, or explicitly 
    39.  * resizes the backing array; merely setting the value of an element is not 
    40.  * a structural modification.)  This is typically accomplished by 
    41.  * synchronizing on some object that naturally encapsulates the list. 
    42.  * 
    43.  * If no such object exists, the list should be "wrapped" using the 
    44.  * {@link Collections#synchronizedList Collections.synchronizedList} 
    45.  * method.  This is best done at creation time, to prevent accidental 
    46.  * unsynchronized access to the list:<pre> 
    47.  *   List list = Collections.synchronizedList(new ArrayList(...));</pre> 
    48.  * 
    49.  * <p>The iterators returned by this class's <tt>iterator</tt> and 
    50.  * <tt>listIterator</tt> methods are <i>fail-fast</i>: if the list is 
    51.  * structurally modified at any time after the iterator is created, in any way 
    52.  * except through the iterator's own <tt>remove</tt> or <tt>add</tt> methods, 
    53.  * the iterator will throw a {@link ConcurrentModificationException}.  Thus, in 
    54.  * the face of concurrent modification, the iterator fails quickly and cleanly, 
    55.  * rather than risking arbitrary, non-deterministic behavior at an undetermined 
    56.  * time in the future.<p> 
    57.  * 
    58.  * Note that the fail-fast behavior of an iterator cannot be guaranteed 
    59.  * as it is, generally speaking, impossible to make any hard guarantees in the 
    60.  * presence of unsynchronized concurrent modification.  Fail-fast iterators 
    61.  * throw <tt>ConcurrentModificationException</tt> on a best-effort basis. 
    62.  * Therefore, it would be wrong to write a program that depended on this 
    63.  * exception for its correctness: <i>the fail-fast behavior of iterators 
    64.  * should be used only to detect bugs.</i><p> 
    65.  * 
    66.  * This class is a member of the 
    67.  * <a href="{@docRoot}/../technotes/guides/collections/index.html" mce_href="technotes/guides/collections/index.html"> 
    68.  * Java Collections Framework</a>. 
    69.  * 
    70.  * @author  Josh Bloch 
    71.  * @author  Neal Gafter 
    72.  * @version 1.56, 04/21/06 
    73.  * @see     Collection 
    74.  * @see     List 
    75.  * @see     LinkedList 
    76.  * @see     Vector 
    77.  * @since   1.2 
    78.  */  
    79. public class ArrayList<E> extends AbstractList<E>  
    80.         implements List<E>, RandomAccess, Cloneable, java.io.Serializable  
    81. {  
    82.     private static final long serialVersionUID = 8683452581122892189L;  
    83.     /** 
    84.      * The array buffer into which the elements of the ArrayList are stored. 
    85.      * The capacity of the ArrayList is the length of this array buffer. 
    86.      */  
    87.     private transient Object[] elementData;  
    88.     /** 
    89.      * The size of the ArrayList (the number of elements it contains). 
    90.      * 
    91.      * @serial 
    92.      */  
    93.     private int size;  
    94.     /** 
    95.      * Constructs an empty list with the specified initial capacity. 
    96.      * 
    97.      * @param   initialCapacity   the initial capacity of the list 
    98.      * @exception IllegalArgumentException if the specified initial capacity 
    99.      *            is negative 
    100.      */  
    101.     public ArrayList(int initialCapacity) {  
    102.     super();  
    103.         if (initialCapacity < 0)  
    104.             throw new IllegalArgumentException("Illegal Capacity: "+  
    105.                                                initialCapacity);  
    106.     this.elementData = new Object[initialCapacity];  
    107.     }  
    108.     /** 
    109.      * Constructs an empty list with an initial capacity of ten. 
    110.      */  
    111.     public ArrayList() {  
    112.     this(10);  
    113.     }  
    114.     /** 
    115.      * Constructs a list containing the elements of the specified 
    116.      * collection, in the order they are returned by the collection's 
    117.      * iterator. 
    118.      * 
    119.      * @param c the collection whose elements are to be placed into this list 
    120.      * @throws NullPointerException if the specified collection is null 
    121.      */  
    122.     public ArrayList(Collection<? extends E> c) {  
    123.     elementData = c.toArray();  
    124.     size = elementData.length;  
    125.     // c.toArray might (incorrectly) not return Object[] (see 6260652)  
    126.     if (elementData.getClass() != Object[].class)  
    127.         elementData = Arrays.copyOf(elementData, size, Object[].class);  
    128.     }  
    129.     /** 
    130.      * Trims the capacity of this <tt>ArrayList</tt> instance to be the 
    131.      * list's current size.  An application can use this operation to minimize 
    132.      * the storage of an <tt>ArrayList</tt> instance. 
    133.      */  
    134.     public void trimToSize() {  
    135.     modCount++;  
    136.     int oldCapacity = elementData.length;  
    137.     if (size < oldCapacity) {  
    138.             elementData = Arrays.copyOf(elementData, size);  
    139.     }  
    140.     }  
    141.     /** 
    142.      * Increases the capacity of this <tt>ArrayList</tt> instance, if 
    143.      * necessary, to ensure that it can hold at least the number of elements 
    144.      * specified by the minimum capacity argument. 
    145.      * 
    146.      * @param   minCapacity   the desired minimum capacity 
    147.      */  
    148.     public void ensureCapacity(int minCapacity) {  
    149.     modCount++;  
    150.     int oldCapacity = elementData.length;  
    151.     if (minCapacity > oldCapacity) {  
    152.         Object oldData[] = elementData;  
    153.         int newCapacity = (oldCapacity * 3)/2 + 1;  
    154.             if (newCapacity < minCapacity)  
    155.         newCapacity = minCapacity;  
    156.             // minCapacity is usually close to size, so this is a win:  
    157.             elementData = Arrays.copyOf(elementData, newCapacity);  
    158.     }  
    159.     }  
    160.     /** 
    161.      * Returns the number of elements in this list. 
    162.      * 
    163.      * @return the number of elements in this list 
    164.      */  
    165.     public int size() {  
    166.     return size;  
    167.     }  
    168.     /** 
    169.      * Returns <tt>true</tt> if this list contains no elements. 
    170.      * 
    171.      * @return <tt>true</tt> if this list contains no elements 
    172.      */  
    173.     public boolean isEmpty() {  
    174.     return size == 0;  
    175.     }  
    176.     /** 
    177.      * Returns <tt>true</tt> if this list contains the specified element. 
    178.      * More formally, returns <tt>true</tt> if and only if this list contains 
    179.      * at least one element <tt>e</tt> such that 
    180.      * <tt>(o==null ? e==null : o.equals(e))</tt>. 
    181.      * 
    182.      * @param o element whose presence in this list is to be tested 
    183.      * @return <tt>true</tt> if this list contains the specified element 
    184.      */  
    185.     public boolean contains(Object o) {  
    186.     return indexOf(o) >= 0;  
    187.     }  
    188.     /** 
    189.      * Returns the index of the first occurrence of the specified element 
    190.      * in this list, or -1 if this list does not contain the element. 
    191.      * More formally, returns the lowest index <tt>i</tt> such that 
    192.      * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, 
    193.      * or -1 if there is no such index. 
    194.      */  
    195.     public int indexOf(Object o) {  
    196.     if (o == null) {  
    197.         for (int i = 0; i < size; i++)  
    198.         if (elementData[i]==null)  
    199.             return i;  
    200.     } else {  
    201.         for (int i = 0; i < size; i++)  
    202.         if (o.equals(elementData[i]))  
    203.             return i;  
    204.     }  
    205.     return -1;  
    206.     }  
    207.     /** 
    208.      * Returns the index of the last occurrence of the specified element 
    209.      * in this list, or -1 if this list does not contain the element. 
    210.      * More formally, returns the highest index <tt>i</tt> such that 
    211.      * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, 
    212.      * or -1 if there is no such index. 
    213.      */  
    214.     public int lastIndexOf(Object o) {  
    215.     if (o == null) {  
    216.         for (int i = size-1; i >= 0; i--)  
    217.         if (elementData[i]==null)  
    218.             return i;  
    219.     } else {  
    220.         for (int i = size-1; i >= 0; i--)  
    221.         if (o.equals(elementData[i]))  
    222.             return i;  
    223.     }  
    224.     return -1;  
    225.     }  
    226.     /** 
    227.      * Returns a shallow copy of this <tt>ArrayList</tt> instance.  (The 
    228.      * elements themselves are not copied.) 
    229.      * 
    230.      * @return a clone of this <tt>ArrayList</tt> instance 
    231.      */  
    232.     public Object clone() {  
    233.     try {  
    234.         ArrayList<E> v = (ArrayList<E>) super.clone();  
    235.         v.elementData = Arrays.copyOf(elementData, size);  
    236.         v.modCount = 0;  
    237.         return v;  
    238.     } catch (CloneNotSupportedException e) {  
    239.         // this shouldn't happen, since we are Cloneable  
    240.         throw new InternalError();  
    241.     }  
    242.     }  
    243.     /** 
    244.      * Returns an array containing all of the elements in this list 
    245.      * in proper sequence (from first to last element). 
    246.      * 
    247.      * <p>The returned array will be "safe" in that no references to it are 
    248.      * maintained by this list.  (In other words, this method must allocate 
    249.      * a new array).  The caller is thus free to modify the returned array. 
    250.      * 
    251.      * <p>This method acts as bridge between array-based and collection-based 
    252.      * APIs. 
    253.      * 
    254.      * @return an array containing all of the elements in this list in 
    255.      *         proper sequence 
    256.      */  
    257.     public Object[] toArray() {  
    258.         return Arrays.copyOf(elementData, size);  
    259.     }  
    260.     /** 
    261.      * Returns an array containing all of the elements in this list in proper 
    262.      * sequence (from first to last element); the runtime type of the returned 
    263.      * array is that of the specified array.  If the list fits in the 
    264.      * specified array, it is returned therein.  Otherwise, a new array is 
    265.      * allocated with the runtime type of the specified array and the size of 
    266.      * this list. 
    267.      * 
    268.      * <p>If the list fits in the specified array with room to spare 
    269.      * (i.e., the array has more elements than the list), the element in 
    270.      * the array immediately following the end of the collection is set to 
    271.      * <tt>null</tt>.  (This is useful in determining the length of the 
    272.      * list <i>only</i> if the caller knows that the list does not contain 
    273.      * any null elements.) 
    274.      * 
    275.      * @param a the array into which the elements of the list are to 
    276.      *          be stored, if it is big enough; otherwise, a new array of the 
    277.      *          same runtime type is allocated for this purpose. 
    278.      * @return an array containing the elements of the list 
    279.      * @throws ArrayStoreException if the runtime type of the specified array 
    280.      *         is not a supertype of the runtime type of every element in 
    281.      *         this list 
    282.      * @throws NullPointerException if the specified array is null 
    283.      */  
    284.     public <T> T[] toArray(T[] a) {  
    285.         if (a.length < size)  
    286.             // Make a new array of a's runtime type, but my contents:  
    287.             return (T[]) Arrays.copyOf(elementData, size, a.getClass());  
    288.     System.arraycopy(elementData, 0, a, 0, size);  
    289.         if (a.length > size)  
    290.             a[size] = null;  
    291.         return a;  
    292.     }  
    293.     // Positional Access Operations  
    294.     /** 
    295.      * Returns the element at the specified position in this list. 
    296.      * 
    297.      * @param  index index of the element to return 
    298.      * @return the element at the specified position in this list 
    299.      * @throws IndexOutOfBoundsException {@inheritDoc} 
    300.      */  
    301.     public E get(int index) {  
    302.     RangeCheck(index);  
    303.     return (E) elementData[index];  
    304.     }  
    305.     /** 
    306.      * Replaces the element at the specified position in this list with 
    307.      * the specified element. 
    308.      * 
    309.      * @param index index of the element to replace 
    310.      * @param element element to be stored at the specified position 
    311.      * @return the element previously at the specified position 
    312.      * @throws IndexOutOfBoundsException {@inheritDoc} 
    313.      */  
    314.     public E set(int index, E element) {  
    315.     RangeCheck(index);  
    316.     E oldValue = (E) elementData[index];  
    317.     elementData[index] = element;  
    318.     return oldValue;  
    319.     }  
    320.     /** 
    321.      * Appends the specified element to the end of this list. 
    322.      * 
    323.      * @param e element to be appended to this list 
    324.      * @return <tt>true</tt> (as specified by {@link Collection#add}) 
    325.      */  
    326.     public boolean add(E e) {  
    327.     ensureCapacity(size + 1);  // Increments modCount!!  
    328.     elementData[size++] = e;  
    329.     return true;  
    330.     }  
    331.     /** 
    332.      * Inserts the specified element at the specified position in this 
    333.      * list. Shifts the element currently at that position (if any) and 
    334.      * any subsequent elements to the right (adds one to their indices). 
    335.      * 
    336.      * @param index index at which the specified element is to be inserted 
    337.      * @param element element to be inserted 
    338.      * @throws IndexOutOfBoundsException {@inheritDoc} 
    339.      */  
    340.     public void add(int index, E element) {  
    341.     if (index > size || index < 0)  
    342.         throw new IndexOutOfBoundsException(  
    343.         "Index: "+index+", Size: "+size);  
    344.     ensureCapacity(size+1);  // Increments modCount!!  
    345.     System.arraycopy(elementData, index, elementData, index + 1,  
    346.              size - index);  
    347.     elementData[index] = element;  
    348.     size++;  
    349.     }  
    350.     /** 
    351.      * Removes the element at the specified position in this list. 
    352.      * Shifts any subsequent elements to the left (subtracts one from their 
    353.      * indices). 
    354.      * 
    355.      * @param index the index of the element to be removed 
    356.      * @return the element that was removed from the list 
    357.      * @throws IndexOutOfBoundsException {@inheritDoc} 
    358.      */  
    359.     public E remove(int index) {  
    360.     RangeCheck(index);  
    361.     modCount++;  
    362.     E oldValue = (E) elementData[index];  
    363.     int numMoved = size - index - 1;  
    364.     if (numMoved > 0)  
    365.         System.arraycopy(elementData, index+1, elementData, index,  
    366.                  numMoved);  
    367.     elementData[--size] = null// Let gc do its work  
    368.     return oldValue;  
    369.     }  
    370.     /** 
    371.      * Removes the first occurrence of the specified element from this list, 
    372.      * if it is present.  If the list does not contain the element, it is 
    373.      * unchanged.  More formally, removes the element with the lowest index 
    374.      * <tt>i</tt> such that 
    375.      * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> 
    376.      * (if such an element exists).  Returns <tt>true</tt> if this list 
    377.      * contained the specified element (or equivalently, if this list 
    378.      * changed as a result of the call). 
    379.      * 
    380.      * @param o element to be removed from this list, if present 
    381.      * @return <tt>true</tt> if this list contained the specified element 
    382.      */  
    383.     public boolean remove(Object o) {  
    384.     if (o == null) {  
    385.             for (int index = 0; index < size; index++)  
    386.         if (elementData[index] == null) {  
    387.             fastRemove(index);  
    388.             return true;  
    389.         }  
    390.     } else {  
    391.         for (int index = 0; index < size; index++)  
    392.         if (o.equals(elementData[index])) {  
    393.             fastRemove(index);  
    394.             return true;  
    395.         }  
    396.         }  
    397.     return false;  
    398.     }  
    399.     /* 
    400.      * Private remove method that skips bounds checking and does not 
    401.      * return the value removed. 
    402.      */  
    403.     private void fastRemove(int index) {  
    404.         modCount++;  
    405.         int numMoved = size - index - 1;  
    406.         if (numMoved > 0)  
    407.             System.arraycopy(elementData, index+1, elementData, index,  
    408.                              numMoved);  
    409.         elementData[--size] = null// Let gc do its work  
    410.     }  
    411.     /** 
    412.      * Removes all of the elements from this list.  The list will 
    413.      * be empty after this call returns. 
    414.      */  
    415.     public void clear() {  
    416.     modCount++;  
    417.     // Let gc do its work  
    418.     for (int i = 0; i < size; i++)  
    419.         elementData[i] = null;  
    420.     size = 0;  
    421.     }  
    422.     /** 
    423.      * Appends all of the elements in the specified collection to the end of 
    424.      * this list, in the order that they are returned by the 
    425.      * specified collection's Iterator.  The behavior of this operation is 
    426.      * undefined if the specified collection is modified while the operation 
    427.      * is in progress.  (This implies that the behavior of this call is 
    428.      * undefined if the specified collection is this list, and this 
    429.      * list is nonempty.) 
    430.      * 
    431.      * @param c collection containing elements to be added to this list 
    432.      * @return <tt>true</tt> if this list changed as a result of the call 
    433.      * @throws NullPointerException if the specified collection is null 
    434.      */  
    435.     public boolean addAll(Collection<? extends E> c) {  
    436.     Object[] a = c.toArray();  
    437.         int numNew = a.length;  
    438.     ensureCapacity(size + numNew);  // Increments modCount  
    439.         System.arraycopy(a, 0, elementData, size, numNew);  
    440.         size += numNew;  
    441.     return numNew != 0;  
    442.     }  
    443.     /** 
    444.      * Inserts all of the elements in the specified collection into this 
    445.      * list, starting at the specified position.  Shifts the element 
    446.      * currently at that position (if any) and any subsequent elements to 
    447.      * the right (increases their indices).  The new elements will appear 
    448.      * in the list in the order that they are returned by the 
    449.      * specified collection's iterator. 
    450.      * 
    451.      * @param index index at which to insert the first element from the 
    452.      *              specified collection 
    453.      * @param c collection containing elements to be added to this list 
    454.      * @return <tt>true</tt> if this list changed as a result of the call 
    455.      * @throws IndexOutOfBoundsException {@inheritDoc} 
    456.      * @throws NullPointerException if the specified collection is null 
    457.      */  
    458.     public boolean addAll(int index, Collection<? extends E> c) {  
    459.     if (index > size || index < 0)  
    460.         throw new IndexOutOfBoundsException(  
    461.         "Index: " + index + ", Size: " + size);  
    462.     Object[] a = c.toArray();  
    463.     int numNew = a.length;  
    464.     ensureCapacity(size + numNew);  // Increments modCount  
    465.     int numMoved = size - index;  
    466.     if (numMoved > 0)  
    467.         System.arraycopy(elementData, index, elementData, index + numNew,  
    468.                  numMoved);  
    469.         System.arraycopy(a, 0, elementData, index, numNew);  
    470.     size += numNew;  
    471.     return numNew != 0;  
    472.     }  
    473.     /** 
    474.      * Removes from this list all of the elements whose index is between 
    475.      * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive. 
    476.      * Shifts any succeeding elements to the left (reduces their index). 
    477.      * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements. 
    478.      * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.) 
    479.      * 
    480.      * @param fromIndex index of first element to be removed 
    481.      * @param toIndex index after last element to be removed 
    482.      * @throws IndexOutOfBoundsException if fromIndex or toIndex out of 
    483.      *              range (fromIndex < 0 || fromIndex >= size() || toIndex 
    484.      *              > size() || toIndex < fromIndex) 
    485.      */  
    486.     protected void removeRange(int fromIndex, int toIndex) {  
    487.     modCount++;  
    488.     int numMoved = size - toIndex;  
    489.         System.arraycopy(elementData, toIndex, elementData, fromIndex,  
    490.                          numMoved);  
    491.     // Let gc do its work  
    492.     int newSize = size - (toIndex-fromIndex);  
    493.     while (size != newSize)  
    494.         elementData[--size] = null;  
    495.     }  
    496.     /** 
    497.      * Checks if the given index is in range.  If not, throws an appropriate 
    498.      * runtime exception.  This method does *not* check if the index is 
    499.      * negative: It is always used immediately prior to an array access, 
    500.      * which throws an ArrayIndexOutOfBoundsException if index is negative. 
    501.      */  
    502.     private void RangeCheck(int index) {  
    503.     if (index >= size)  
    504.         throw new IndexOutOfBoundsException(  
    505.         "Index: "+index+", Size: "+size);  
    506.     }  
    507.     /** 
    508.      * Save the state of the <tt>ArrayList</tt> instance to a stream (that 
    509.      * is, serialize it). 
    510.      * 
    511.      * @serialData The length of the array backing the <tt>ArrayList</tt> 
    512.      *             instance is emitted (int), followed by all of its elements 
    513.      *             (each an <tt>Object</tt>) in the proper order. 
    514.      */  
    515.     private void writeObject(java.io.ObjectOutputStream s)  
    516.         throws java.io.IOException{  
    517.     // Write out element count, and any hidden stuff  
    518.     int expectedModCount = modCount;  
    519.     s.defaultWriteObject();  
    520.         // Write out array length  
    521.         s.writeInt(elementData.length);  
    522.     // Write out all elements in the proper order.  
    523.     for (int i=0; i<size; i++)  
    524.             s.writeObject(elementData[i]);  
    525.     if (modCount != expectedModCount) {  
    526.             throw new ConcurrentModificationException();  
    527.         }  
    528.     }  
    529.     /** 
    530.      * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is, 
    531.      * deserialize it). 
    532.      */  
    533.     private void readObject(java.io.ObjectInputStream s)  
    534.         throws java.io.IOException, ClassNotFoundException {  
    535.     // Read in size, and any hidden stuff  
    536.     s.defaultReadObject();  
    537.         // Read in array length and allocate array  
    538.         int arrayLength = s.readInt();  
    539.         Object[] a = elementData = new Object[arrayLength];  
    540.     // Read in all elements in the proper order.  
    541.     for (int i=0; i<size; i++)  
    542.             a[i] = s.readObject();  
    543.     }  
    544. }  
  • 相关阅读:
    PVT--无卷积密集预测的多功能backbone
    MobileNet系列之MobileNet_v3
    MobileNet系列之MobileNet_v2
    CVPR2021 | 开放世界的目标检测
    Siamese network总结
    文字识别OCR开源框架的对比--Tesseract vs EasyOCR
    CVPR2021|一个高效的金字塔切分注意力模块PSA
    Boltdb学习笔记之二--数据结构
    C++关键字之likely和unlikely
    Boltdb学习笔记之〇--概述
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/3581494.html
Copyright © 2011-2022 走看看