aggregate
Java collection class is a kind of container, which can hold other data. It is used to store multiple objects with different quantities. It can also be used to store associative arrays (data pairs) with mapping relationships
Overall,
According to different storage data formats (single column or double column), it can be simply divided into two categories: Collection and Map
Collection
A collection is like a container, adding or taking things in and out, corresponding to adding or deleting. The collection class provides corresponding methods for these functions.
Collection is the parent interface of List and Set interfaces. The methods defined in this interface can be used to operate not only Set sets, but also List and Queue sets.
JDK does not provide any direct implementation of this interface, but provides more specific implementation of sub interfaces (such as Set and List)
Common abstract methods defined in Collection:
- add to
add(Object obj)
addAll(Collection coll) - Get the number of valid elements
int size() - Empty collection
void clear() - Is it an empty collection
boolean isEmpty() - Whether to include an element
boolean contains(Object obj) - delete
boolean remove will only delete the first element found - Are sets equal
boolean equals(Object obj) - Gets the hash value of the collection object
hashCode() - ergodic
iterator(): returns an iterator object for collection traversal
List
- Because of the limitation of storing data in array, it is used to replace array
- The elements are ordered and repeatable. Each element corresponds to an integer serial number. The elements in the container can be accessed according to the serial number
- Main implementation classes: ArrayList, LinkedList and Vector
Common methods: add, delete, modify and check
- void add(int index, Object ele): inserts an ele element at the index position
- Object remove(int index): removes the element at the specified index position and returns this element
- Object set(int index, Object ele): sets the element of the specified index position to ele
- 2.Object get(int index): get the element ele at the specified index position
ArrayList
The main implementation class of List. In essence, the ArrayList object reference points to a 'variable length array'
Add, delete, modify and query ArrayList:
public static void main(String[] args) { // Note that generics are consistent with iterators or traversal statements List<String> list = new ArrayList(); // Add element list.add("a"); list.add("b"); list.add("c"); list.add("z"); // Output list form System.out.println("toString Form:"); System.out.println(list); // for each System.out.println("enhance for Cycle:"); for (String val : list) { System.out.println(val); } // for loop // Note: the size of the container is size(), not length() System.out.println("for Cycle: "); for (int i = 0; i < list.size(); i++) { System.out.println("waiting..."); } // Delete element list.remove("b"); // Subscript starts at 0 list.remove(1); // Modify element list.set(0, "aka hh"); // Using iterator loops // The container has its own iterator() method, and List implements the Collection interface, which can be used directly come out System.out.println("iterator iterator : "); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } }
Operation results:
ArrayList capacity expansion mechanism:
- After java8, ArrayList is similar to lazy style. At the beginning, an array with length of 0 is created. When the first element is added, an array with capacity of 10 is created, and 10 is its default initial capacity
/** * Default initial capacity. */ private static final int DEFAULT_CAPACITY = 10;
- The capacity expansion operation is mainly performed by the following statements,
By default, the capacity expansion is 1.5 times (1 + 0.5) of the original array and shifted to the right by 1
int newCapacity = oldCapacity + (oldCapacity >> 1);
After capacity expansion according to the default value, judge whether the length of the new array meets the requirements. If it meets the requirements, copy the data of the original array to the new array to complete the capacity expansion operation.
/** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); 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: elementData = Arrays.copyOf(elementData, newCapacity); }
Essence of capacity expansion:
Open up a larger array space and copy the data in the original array to the new array
LinkedList
The bottom layer is realized by linked list. Due to the natural attributes of linked list, it is recommended to use LinkedList class for frequent operations of inserting or deleting elements, which is more efficient
LinkedList<String> list = new LinkedList<>();
Create the above ArrayList as a LinkedList, and keep the other statements unchanged. You can also get the following running results:
Vector
Vector is thread safe
When reusing the List container, it is best to make ArrayList the default choice. Use LinkedList when inserting and deleting frequently; Vector is always slower than ArrayList, so try to avoid using it
List summary
Similarities and differences between the three:
-
Vector is thread safe and the other two are non thread safe
-
ArrayList and LinkedList:
ArrayList implements the data structure based on dynamic array. For random access to get and set, ArrayList feels better than LinkedList because LinkedList needs to move the pointer
LinkedList is based on the data structure of linked list. For * * add and delete operations *, LinkedList has an advantage because ArrayList needs to move data -
ArrayList and Vector
The two are almost identical. The only difference is that vector is a synchronized class and belongs to a strongly synchronized class. Therefore, the overhead is larger and the access is slower than ArrayList. Vector requests twice its size for each expansion, while ArrayList is 1.5 times
Set
The concept of Set is similar to that of a box. Things can be thrown into the box "at will", and there is no fixed position. Therefore, it is impossible to find through the index, which requires that the stored elements cannot be repeated.
Set determines whether two objects are the same, not using the = = operator, but according to the equals() method
HashSet
The main implementation class of the Set interface has no duplicate elements. When adding data to the HashSet, the HashSet stores the object according to the hashcode value of the object, and can quickly locate the element according to the hashcode value. The surface is disordered, but in fact it is ordered. The order comes from hashcode
characteristic:
- The order of elements cannot be guaranteed
- HashSet is not thread safe
- Collection elements can be null
For objects stored in the Set container, the corresponding classes must override the equals() and hashCode(Object obj) methods to implement the object equality rule. That is: "equal objects must have equal hash codes".
Judge whether two elements are equal: hashCode() is equal & & equals() is equal.
Implementation and usage of HashSet:
HashSet<String> list = new HashSet<>(); // Add element list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.add("e"); // Output list form System.out.println("toString Form:"); System.out.println(list); // for each System.out.println("enhance for Cycle:"); for (String val : list) { System.out.println(val); } // Delete element list.remove("b"); // Using iterator loops System.out.println("iterator iterator : "); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); }
Since the elements in the Set do not have the concept of subscript, the subscript cannot be used to access the elements. Only the above iterator or for each can be used to access the Set elements
Accordingly, the method of deleting elements can only delete specific elements according to the content
To add an element to a HashSet:
- HashSet will call the hashCode() method of the object to get the hashCode value, and then determine the storage location of the object in the underlying array of HashSet through hash function according to the hashCode value. (the hash function will calculate the subscript in the array by comparing the length of the underlying array)
- If the hashCode() values of the two elements are equal, the equals method will be called again. If the equals method results in true, the addition fails; If it is false, the element will be saved, but there are already elements in the position of the array, and the link will continue through a linked list.
If the hashcode() value is equal and the equals() result is true, then the two elements are equal - If the equals() method of two elements returns true, but their hashCode() return values are not equal, the hashSet will store them in different locations, but they can still be added successfully.
HashSet expansion method:
* @param c the collection whose elements are to be placed into this set * @throws NullPointerException if the specified collection is null */ public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); }
LinkedHashSet
It is a subclass of HashSet. The element storage location is determined according to the hashCode value of the element, and the storage order is maintained by using a two-way linked list. Similarly, duplicate elements are not allowed
TreeSet
- The bottom layer uses red black tree to store data
- Make sure the data is sorted
ps: the tree structure belongs to the content of the data structure, which is not well understood at present. It will be supplemented later