Set frame learning

Posted by Lerris on Mon, 28 Feb 2022 10:22:34 +0100

Set frame diagram

Note: the dotted line corresponds to the interface and the solid line corresponds to the implementation class

Top level interfaces: Collection and Map

Interface is to provide methods
The Collection interface indicates that the stored data is a Collection composed of single data;
The Map interface represents a collection of key value pairs stored.

public class CollectionTest {
    public static void main(String[] args) {
        //ArrayList is the implementation class of Collection: it stores a single element
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(23);
        arrayList.add(45);

        //HashMap is a Map interface implementation class: key value pair
        HashMap<String,String> hashMap =  new HashMap<String,String>();
        hashMap.put("k1","v1");
    }
}

1: Three sub interfaces of Collection:
List: a collection that allows the storage of duplicate elements;
Set: it is not allowed to store a set of duplicate elements (de duplication);
Queue: mainly used to store data, simulation queue (FIFO), simulation stack (FIFO) and priority queue; Can be repeated;

2: Map interface: stores key value pairs
SortMap: sort elements

Implementation class features

1: Implementation class of List interface:
ArrayList: the query speed is fast. The bottom layer stores elements based on arrays and encapsulates a dynamic Object [] array. It is a set of sequential storage (insertion order);
ListedList: the addition and deletion speed is fast, and the thread is unsafe. The bottom layer is a two-way linked list implementation, and the elements are inserted in order;
Vector: thread safe. Query addition and deletion is slow and has been replaced by ArrayList.

2: Implementation class of Set interface:
HashSet: the underlying data structure is implemented based on HashMap. The thread is unsafe and the order of elements in the set is not guaranteed, that is, the consistency of data and insertion order cannot be guaranteed
LinkedSet: the underlying data structure is implemented based on LinkedHashMap. The thread is unsafe, which can ensure the consistency of data and insertion order
TreeSet: Based on the implementation of TreeMap set, the thread is unsafe and the data is orderly (sorted according to the characteristics of attributes)

3: Implementation class of Map interface: stores key value pairs
HashMap: the bottom layer is a hash table structure. The thread is unsafe. The key value is allowed to be null, and the key cannot be repeated (related to the hash table structure)
HashTable: similar to HashMap, the bottom layer is the hash table interface, thread safe, and the key value cannot be null
LinkedHashMap: it is a subclass of HashMap, which can ensure that the data insertion is orderly
TreeMap: the bottom layer is a binary tree: red black tree. The thread is not safe. The data can be sorted based on attribute characteristics

Methods provided by the Collection interface


   ArrayList<Integer> arrayList = new ArrayList<Integer>();
        /**
         * Add a single element
         * boolean add(E e)
         * Return value Boolean type: true: successful insertion; false: failed insertion
         */
        arrayList.add(23);
        arrayList.add(45);

        ArrayList<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(15);
        list.add(17);
        HashSet<Integer> hashSet = new HashSet<>();
        hashSet.add(55);
        hashSet.add(78);
        /**
         * Batch add elements
         * boolean addAll(Collection<? extends E> c)
         * Return value Boolean type: true: successful insertion; false: failed insertion
         */
        arrayList.addAll(hashSet);

        for (Integer i : arrayList) {
            System.out.print(i + " ");
        }
        System.out.println();
        System.out.println("------");

        /**
         * Delete elements in the collection
         * void clear()
         */
//        arrayList.clear();
//        for (Integer i:arrayList) {
//            System.out.print(i+" ");
//        }
        /**
         * Determines whether the current collection contains the specified element
         * boolean contains(Object o)
         * Return value Boolean type true: exists false: does not exist
         */
        boolean b = arrayList.contains(55);
        System.out.println(b);
        /**
         * Judge whether the set is empty
         * boolean isEmpty()
         */
        boolean empty = arrayList.isEmpty();
        System.out.println(empty);

        /**
         * Traversing a collection using iterators
         * Iterator is a design pattern whose main function is to traverse the container / collection without exposing the internal implementation details inside the collection
         *Iterator<E> iterator()
         * Returns an object of type Iterator
         * Methods provided under this type:
         * hasNext(): Determine whether the next element still exists in the container
         * next():Get current element
         */
        Iterator<Integer> iterator = arrayList.iterator();
        while (iterator.hasNext()) {
            Integer value = iterator.next();
            System.out.print(value+" ");
        }
        System.out.println();
        System.out.println("-----");

        /**
         * for( : )
         * foreach Traversing the bottom layer or using iterators
         * The format is: for (element type in the collection element alias: collection instance)
         */
        for (Integer n:arrayList
             ) {
            System.out.print(n+" ");

        }

        System.out.println();
//        /**
//         * Deletes the specified element object o
//         * boolean remove(Object o)
//         * The type returned is Boolean
//         */
//        boolean remove1 = arrayList.remove(Integer.valueOf(23));
//        System.out.print("delete data 1:" + remove1);
//        System.out.println();
//        /**
//         * Delete the element at the specified index position
//         * E remove(int index)
//         * The element type is returned, and the element at the deleted position is returned
//         */
//        Integer remove = arrayList.remove(1);
//        System.out.print("deleted data:" + remove);
//
//        System.out.println("-----");
//        for (Integer a:arrayList
//                ) {
//            System.out.print(a+" ");
//
//        }
//        System.out.println("-----");
//
       ArrayList<Integer> list1 =  new ArrayList<>();
       list1.add(45);
       list1.add(2);
       list1.add(78);
       list1.add(56);
        for (Integer n:list1
                ) {
            System.out.print(n+" ");

        }
        System.out.println();
        System.out.println("----");
        /**
         *arrayList:23 45 55 78
         * list1:45 2 78 56
         * Save the data shared by the current set for data saving (find the intersection of the two sets)
         * boolean retainAll(Collection<?> c)
         */
//        boolean a =arrayList.retainAll(list1);
//        System.out.println(a);

        /**
         * Gets the number of elements in the current collection
         * int size()
         */
        int size = arrayList.size();
        System.out.println(size);
        
        
        for (Integer n:arrayList
                ) {
            System.out.print(n+" ");

        }

practice:

/**
         * Union: gets all the elements in two sets
         * Intersection: get the same elements in two sets
         * Difference set: the difference set of a and b, that is, I have what you don't have
         */

        ArrayList <Integer> a = new ArrayList <Integer>();
        a.add(1);
        a.add(2);
        a.add(3);

        ArrayList <Integer> b = new ArrayList <Integer>();
        b.add(3);
        b.add(4);
        b.add(5);

        /**
         * Union: 1 2 3 4 5
         * Intersection: 3
         * (a And b) difference set: 1 2
         */
        
        //Union
        a.addAll(b);
        
        //intersection
        a.retainAll(b);
        
        //Difference set
        a.removeAll(b);

Working principle and implementation of ArrayList

Features: you need to view the implementation logic through the underlying implementation of the source code
① Use and characteristics of ArrayList set:
**Features: * * 1. Elements are stored and inserted in the same order
2. The data can be repeated
3. Can store null
4. The underlying data structure is an array
5. It can be dynamically expanded. The default capacity is 10
6. The expansion is based on 1.5 times the original size
Constructor:

 //Nonparametric structure
        ArrayList<Integer> list = new ArrayList<Integer>();
        //Instantiate by specifying the size of the collection capacity
        ArrayList<Integer> list1 = new ArrayList<>(100);
        //Instantiate a Collection through the Collection instance
        ArrayList<Integer> list2 = new ArrayList<>(list);

Study the implementation of ArrayList through JDK source code
1. Focus on inheritance
2. Properties and default values
3. Constructor
4. Capacity expansion mechanism and timing
5. Underlying data structure (array, linked list, queue, stack, hash table...)
6. Implementation principle of common methods (add,remove,get...)

ArrayList:
Inheritance relationship:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

Inheriting from AbstractList, AbstractList is an abstract class that implements the List interface. It is an array queue that provides the implementation of related basic functions such as addition, deletion, modification and traversal. The method subclass reuses the method. If the subclass has special functions, it can override the method of the parent class;

ArrayList implements the list interface, which inherits from the collection interface. Based on the methods provided by the collection interface, some new methods are provided, such as get, set, add and other unique methods;

ArrayList implements RandomAccess interface, which provides random access function and fast access function for list;

ArrayList implements the Cloneable interface, that is, it contains the function clone (), which can be cloned;

ArrayList implements the Serializable interface, which means that ArrayList supports serialization de transmission (IO)

Properties and defaults:

//The default initial capacity is 10
    private static final int DEFAULT_CAPACITY = 10;
//Empty array instance
    private static final Object[] EMPTY_ELEMENTDATA = {};
//An array is used to store data. The data type stored in the array is Object
   private transient Object[] elementData; 
//Used to record the number of stored data
    private int size;

The underlying storage elements of ArrayList are arrays
Array elementdata Length: indicates the current array capacity and the maximum number of data stored
*size: * number of data actually stored

Constructor:

//Parameterized constructor: instantiate ArrayList by specifying initial capacity initialCapacity
public ArrayList(int initialCapacity) {
        super();
        //Parameter verification
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
        //Instantiate an array with the size of initialCapacity and assign the array to elementData
        this.elementData = new Object[initialCapacity];
    }

//non-parameter constructor 
    public ArrayList() {
        super();
        //Given an empty array
        this.elementData = EMPTY_ELEMENTDATA;
        //Assign the default value in add
    }


   //Instantiate ArrayList through collection instances
    public ArrayList(Collection<? extends E> c) {
    //Convert the set into an array and assign it directly to elementData
        elementData = c.toArray();
        //Assign the size of existing elements in the collection to size
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            //Complete data copy
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }

Common methods source code analysis:
Add: add element

    public boolean add(E e) {
    //Consider capacity expansion
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //Insert the new element at the end of the elementData array and Match size+1
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
        //When the array is empty, get the current capacity value
        if (elementData == EMPTY_ELEMENTDATA) {
            //When adding the first element, the if method will be entered for the first time when there is no instance of parameter construction
            //When the array size is not specified, the default is 10
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }
 private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        //Insufficient data space, consider capacity expansion 
        if (minCapacity > elementData.length )
            grow(minCapacity);
    }
//Expansion point
private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
       //Expansion size oldcapacity > > 1 = > oldcapacity / 2, i.e. 1.5 times
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //Limitation of expansion range
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        //Create a new set of specified size and copy the original data to the new array
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

    modCount It's a version controller, too ArrayList Properties in (inherited from) AbstractList Attributes in) have nothing to do with business. They are only used for version control. When the collection is changed (added, deleted or modified), 1 will be added automatically
    Capacity expansion mechanism and timing: when the number of data to be inserted is greater than the capacity of the array, the capacity needs to be expanded according to 1% of the size of the original array.5 For capacity expansion, you need to copy the original set data to the new array
add Process:
       1,If the storage array is empty, get the default size value of 10
       2,If the size needs to exceed the size of the array, consider expanding the capacity according to 1% of the original array size.5 Double expansion
       3,Copy the element group size into the new array by creating a new array
       4,Insert the new element into the last size Location and alignment size Add 1 operation


Get: get element

 public E get(int index) {
       //Check the validity of the query location index < size
        rangeCheck(index);

        return elementData(index);
    }
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

 E elementData(int index) {
        return (E) elementData[index];
    }

remove: deletes the element

 public boolean remove(Object o) {
 //Delete operation determines whether the value is null. If it is null, use = = if it is not null, use equals
        if (o == null) {
            //When element is empty
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            //Not empty 
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }
    //Move the subsequent data forward one bit
 private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
 //Arrays.copyof() copy and system Arraycopy copy
 //Set the last position to null and set size-1
        elementData[--size] = null; // clear to let GC do its work
    }

Arrays.copyof()Copy and System.arraycopy Copy:
1,use Arrays.copyOf() Method does not need the information of the target array, but only the length information of the source array and the copied data. The length of the returned new array is the length of the copied data;

2,use System.arraycopy() Method when copying an array, it needs the information of the target array, the original array, the copy position of the original array, the copy position and copy length of the target array;

3,Arrays.copyOf() There are also calls at the bottom System.arraycopy() . 

Topics: Java set