Getting started with java collections and in-depth learning, just read this article

Collection frame:

The collection framework categories in Java can be divided into Collection and Map; the difference between the two:

  • Collection is a single-column collection; Map is a two-column collection

  • Only the Set series in the Collection requires unique elements; the keys in the Map need to be unique, and the values ​​can be repeated

  • Collection's data structure is for elements; Map's data structure is for keys.

Generics:

Before talking about the two collection systems, let’s talk about generics, because they will be used in later collections; the so-called generics are: parameterization of types

Generics are part of a type, class name + generics are a whole

If there is a generic type, when it is not used, the type of the parameter will be automatically promoted to the Object type. If it is taken out again, it needs to be forced downward, and a type conversion exception (ClassCaseException) may occur; The type of elements added to the directional collection causes trouble in post-processing.

The following is a comparison of the difference between adding generics and not adding generics:

package  好好学java;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Test {

    public static void main(String[] args) {
        // 不加泛型,添加和遍历
        List list = new ArrayList<>();
        list.add(1);
        list.add("123");
        list.add("hello");
        
        Iterator it = list.iterator();
        while(it.hasNext()){
            // 没有添加泛型,这里只能使用Object接收
            Object obj = it.next();
            System.out.println(obj);
        }
    }

}
package  好好学java;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Test {

    public static void main(String[] args) {
        // 加泛型,添加和遍历
        List<String> list = new ArrayList<String>();
        list.add("123");
        list.add("hello");
        
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            // 因为添加了泛型,就说明集合中装的全部都是String类型的数据
            // 所以这里用String类型接收,就不会发生异常,并且可以使用String的方法
            String str = it.next();
            System.out.println(str.length());
        }
    }

}

Custom class with generics:

package  好好学java;


public class Test {
    // 自定义一个带有一个参数的泛型类,可以向传入什么类型就传入什么类型
    public static void main(String[] args) {
        // 进行测试, 传入一个String对象
        Person<String> perStr = new Person<String>();
        perStr.setT("我是字符串");
        String str = perStr.getT();
        System.out.println(str);
        
        // 进行测试,传入一个Integer对象
        Person<Integer> perInt = new Person<Integer>();
        perInt.setT(100);
        Integer intVal = perInt.getT();
        System.out.println(intVal);
        
    }

}
//自定义一个带有一个参数的泛型类
class Person<T>{
    private T t;
    
    void setT(T t){
        this.t = t;
    }
    
    T getT(){
        return t;
    }
}

Implement an interface type with generics:

While implementing the interface, the generic type in the interface is specified. (determined when defining the class);

public class GenericImpl1 implements GenericInter<String> {}

When implementing an interface, the generic type in the interface is not specified. In this case, the implementation class of the interface needs to be defined as a generic class. The type of the interface needs to be truly determined when the implementation class object is created. (The type is always uncertain , until the type is determined when the object is created);

public class GenericImpl2<T> implements GenericInter<T> {}

Generic wildcard (?):

Upper limit: such as when defining a method,public void getFunc(List<? extends Animal> an),

Then it means that the parameters here can be passed to Animal, or a subclass of Animal

Lower limit: For example, when defining a method,public void getFunc(Set<? super Animal> an ),

Then it means that the parameters here can be passed to Animal, or the parent class of Animal

Notes on using generics:

1. Generics do not support basic data types

2. Generics do not support inheritance and must be consistent (for example, this is wrong:List<Object> list = new ArrayList<String>();

Collection system:

The collection includes two systems,List和Set

Features of List:

The access is ordered, there is an index, the value can be taken according to the index, and the elements can be repeated

Features of Set:

Unordered access, elements cannot be repeated

List:

Below is ArrayList,LinkedList,Vector(obsolete)

The biggest purpose of collection is to access; List collection is characterized by orderly access, which can store repeated elements, and can use subscripts to perform element operations

ArrayList: The bottom layer is implemented using arrays, so the query speed is fast, and the addition and deletion speed is slow

package  好好学java;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


public class Test {
    // 使用ArrayList进行添加和遍历
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        
        list.add("接口1");
        list.add("接口2");
        list.add("接口3");
        
        // 第一种遍历方式,使用迭代器
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String next = it.next();
            System.out.println(next);
        }
        System.out.println("-------------------");
        // 第二种遍历方式,使用foreach
        for (String str : list){
            System.err.println(str);
        }
    }

}

LinkedList: It is implemented based on the linked list structure, so the query speed is slow, the addition and deletion speed is fast, and a special method is provided to operate (add, delete, check) the elements at the head and tail.

Use LinkedList to implement stacks and queues; stacks are first-in, last-out, and queues are first-in, first-out

package com.xiaoshitou.classtest;

import java.util.LinkedList;

/**
 * 利用LinkedList来模拟栈
 * 栈的特点:先进后出
 * @author Beck
 *
 */
public class MyStack {
    private LinkedList<String> linkList = new LinkedList<String>();
    
    // 压栈
    public void push(String str){
        linkList.addFirst(str);
    }
    
    // 出栈
    public String pop(){
        return linkList.removeFirst();
    }
    
    // 查看
    public String peek(){
        return linkList.peek();
    }
    
    // 判断是否为空
    public boolean isEmpty(){
        return linkList.isEmpty();
    }
}

package  好好学java;



public class Test {
    public static void main(String[] args) {
        // 测试栈
        StackTest stack = new StackTest();
        stack.push("我是第1个进去的");
        stack.push("我是第2个进去的");
        stack.push("我是第3个进去的");
        stack.push("我是第4个进去的");
        stack.push("我是第5个进去的");
        // 取出
        while (!stack.isEmpty()){
            String pop = stack.pop();
            System.out.println(pop);
        }
        // 打印结果
        /*我是第5个进去的
        我是第4个进去的
        我是第3个进去的
        我是第2个进去的
        我是第1个进去的*/
    }
    

}

LinkedList implements Queue:

package  好好学java;

import java.util.LinkedList;

/**
 * 利用linkedList来实现队列
 * 队列: 先进先出
 * @author Beck
 *
 */
public class QueueTest {
    private LinkedList<String> link = new LinkedList<String>();
    
    // 放入
    public void put(String str){
        link.addFirst(str);
    }
    
    // 获取
    public String get(){
        return link.removeLast();
    }
    
    // 判断是否为空
    public boolean isEmpty(){
        return link.isEmpty();
    }
}
package  好好学java;

public class Test {
    public static void main(String[] args) {
        // 测试队列
        QueueTest queue = new QueueTest();
        
        queue.put("我是第1个进入队列的");
        queue.put("我是第2个进入队列的");
        queue.put("我是第3个进入队列的");
        queue.put("我是第4个进入队列的");
        
        // 遍历队列
        while (!queue.isEmpty()){
            String str = queue.get();
            System.out.println(str);
        }
        // 打印结果
        /*我是第1个进入队列的
        我是第2个进入队列的
        我是第3个进入队列的
        我是第4个进入队列的*/

    }
    

}

Vector: Because it is outdated, it is replaced by ArrayList; it also has an iterator obtained through vector.elements(), and the method to determine whether there is an element and to get the element is: hasMoreElements(),nextElement().

package  好好学java;

import java.util.Enumeration;
import java.util.Vector;

public class Test {
    public static void main(String[] args) {
        Vector<String> vector = new Vector<String>();
        
        vector.add("搜索");
        vector.add("vector");
        vector.add("list");
        
        Enumeration<String> elements = vector.elements();
        while (elements.hasMoreElements()){
            String nextElement = elements.nextElement();
            System.out.println(nextElement);
        }
    }
    

}

Set:

The characteristics of the Set collection: the elements are not repeated, the access is disordered, and the subscripted Set collection is as follows:HashSet,LinkedHashSet,TreeSet

HashSet stores strings:

package  好好学java;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        // 利用HashSet来存取
        Set<String> set = new HashSet<String>();
        
        set.add("我的天");
        set.add("我是重复的");
        set.add("我是重复的");
        set.add("welcome");
        
        // 遍历 第一种方式 迭代器
        Iterator<String> it = set.iterator();
        while(it.hasNext()){
            String str = it.next();
            System.out.println(str);
        }
        
        System.out.println("--------------");
        for (String str : set){
            System.out.println(str);
        }
        // 打印结果,重复的已经去掉了
        /*我的天
        welcome
        我是重复的
        --------------
        我的天
        welcome
        我是重复的*/
    }
    

How does the hash table ensure the uniqueness of the elements? The hash table is jointly guaranteed by the hashCode and equals methods.

The stored data process of the hash table (the bottom layer of the hash table also maintains an array):

Calculate the hashCode value according to the stored element, and then calculate the stored subscript according to the calculated hashCode value and the length of the array; if there is no element in the subscript position, store it directly; if there is an element, use the stored subscript The element and the element perform the equals method. If the result is true, there is already the same element, so it does not exist directly; if the result is false, it is stored in the form of a linked list.

Demonstrate HashSet to store custom objects:

package  好好学java;

public class Person {
    // 属性
    private String name;
    private int age;
    
    // 构造方法
    public Person() {
        super();
        
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    
    // 要让哈希表存储不重复的元素,就必须重写hasCode和equals方法
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    
    
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    // getter & setter
   
    ...
    
}

package  好好学java;

import java.util.HashSet;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        // 利用HashSet来存取自定义对象 Person
        Set<Person> set = new HashSet<Person>();
        
        set.add(new Person("cy", 12));
        set.add(new Person("李四", 13));
        set.add(new Person("王五", 22));
        set.add(new Person("cy", 12));
        
        // 遍历
        for (Person p : set){
            System.out.println(p);
        }
        // 结果:向集合中存储两个cy对象,但是集合中就成功存储了一个
        /*Person [name=王五, age=22]
        Person [name=李四, age=13]
        Person [name=cy, age=12]*/
    }
    

}

Therefore, when storing custom objects in the HashSet collection, in order to ensure the uniqueness of the set collection, the hashCode and equals methods must be rewritten.

LinkedHashSet:

It is implemented based on linked list and hash table, so it has orderly access and unique elements.

package  好好学java;

import java.util.LinkedHashSet;

public class Test {
    public static void main(String[] args) {
        // 利用LinkedHashSet来存取自定义对象 Person
        LinkedHashSet<Person> set = new LinkedHashSet<Person>();
        
        set.add(new Person("cy", 12));
        set.add(new Person("李四", 13));
        set.add(new Person("王五", 22));
        set.add(new Person("cy", 12));
        
        // 遍历
        for (Person p : set){
            System.out.println(p);
        }
        // 结果:向集合中存储两个cy对象,但是集合中就成功存储了一个,
        // 并且存进的顺序,和取出来的顺序是一致的
        /*Person [name=cy, age=12]
        Person [name=李四, age=13]
        Person [name=王五, age=22]*/
    }
    

}

TreeSet:

**Features:** Unordered access, unique elements, and can be sorted (sorting is done when adding).

TreeSet is a data structure based on binary tree, binary tree: no more than two nodes under one node.

Stored procedure for binary tree:

If it is the first element, it will be stored directly as the root node, and the next element will be compared with the node. The following elements come in and are compared in turn until there is a place to store them

The TreeSet collection stores String objects

package  好好学java;

import java.util.TreeSet;


public class Test {
    public static void main(String[] args) {
        TreeSet<String> treeSet = new TreeSet<String>();
        treeSet.add("abc");
        treeSet.add("zbc");
        treeSet.add("cbc");
        treeSet.add("xbc");
        
        for (String str : treeSet){
            System.out.println(str);
        }
        // 结果:取出来的结果是经过排序的
        /*
        abc
        cbc
        xbc
        zbc*/
    }
    

}

TreeSet guarantees the uniqueness of elements in two ways:

1. The custom object implements the Comparable interface and rewrites the comparaTo method. This method returns 0 to indicate equality, and less than 0 indicates that the element to be stored is smaller than the element to be compared, otherwise it is greater than 0;

2. When creating a TreeSet, pass in the Comparator interface implementation class object to the constructor, and implement the Comparator interface to override the compara method.

If a custom object is stored in the TreeSet, the custom class does not implement the Comparable interface, or the Comparator comparator is not passed in, a ClassCastException exception will occur

The following is a demonstration of two ways to store custom objects

package  好好学java;
public class Person implements Comparable<Person>{
    // 属性
    private String name;
    private int age;
    
    // 构造方法
    public Person() {
        super();
        
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    
    // 要让哈希表存储不重复的元素,就必须重写hasCode和equals方法
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    
    
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    // getter & setter
   ...
    
    @Override
    public int compareTo(Person o) {
        int result = this.age - o.age;
        if (result == 0){
            return this.name.compareTo(o.name);
        }
        return result;
    }
    
    
}

package  好好学java;

import java.util.TreeSet;


public class Test {
    public static void main(String[] args) {
        // 利用TreeSet来存储自定义类Person对象
        TreeSet<Person> treeSet = new TreeSet<Person>();
        // Person类实现了Comparable接口,并且重写comparaTo方法
        // 比较规则是先按照 年龄排序,年龄相等的情况按照年龄排序
        treeSet.add(new Person("张山1", 20));
        treeSet.add(new Person("张山2", 16));
        treeSet.add(new Person("张山3", 13));
        treeSet.add(new Person("张山4", 17));
        treeSet.add(new Person("张山5", 20));
        
        for (Person p : treeSet){
            System.out.println(p);
        }
        // 结果:按照comparaTo方法内的逻辑来排序的
        /*
        Person [name=张山3, age=13]
        Person [name=张山2, age=16]
        Person [name=张山4, age=17]
        Person [name=张山1, age=20]
        Person [name=张山5, age=20]
         */
        
    }
    

}

Another way: use Comparator

package  好好学java;


public class Person{
    // 属性
    private String name;
    private int age;
    
    // 构造方法
    public Person() {
        super();
        
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    
    // 要让哈希表存储不重复的元素,就必须重写hasCode和equals方法
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    
    
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    // getter & setter
   ...
    
}

package  好好学java;

import java.util.Comparator;
import java.util.TreeSet;


public class Test {
    public static void main(String[] args) {
        // 利用TreeSet来存储自定义类Person对象
        // 创建TreeSet对象的时候传入Comparator比较器,使用匿名内部类的方式
        // 比较规则是先按照 年龄排序,年龄相等的情况按照年龄排序
        TreeSet<Person> treeSet = new TreeSet<Person>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                if (o1 == o2){
                    return 0;
                }
                int result = o1.getAge() - o2.getAge();
                if (result == 0){
                    return o1.getName().compareTo(o2.getName());
                }
                return result;
            }
            
        });

        treeSet.add(new Person("张山1", 20));
        treeSet.add(new Person("张山2", 16));
        treeSet.add(new Person("张山3", 13));
        treeSet.add(new Person("张山4", 17));
        treeSet.add(new Person("张山5", 20));
        
        for (Person p : treeSet){
            System.out.println(p);
        }
        // 结果:按照compara方法内的逻辑来排序的
        /*
        Person [name=张山3, age=13]
        Person [name=张山2, age=16]
        Person [name=张山4, age=17]
        Person [name=张山1, age=20]
        Person [name=张山5, age=20]
         */
        
    }
    

}

Comparator summary:

Collection system summary:

  • List : "Features:" Access is ordered, elements have indexes, and elements can be repeated.

  • ArrayList: Array structure, fast query, slow addition and deletion, thread unsafe, so high efficiency.

  • Vector: Array structure, fast query, slow addition and deletion, thread safety, so low efficiency.

  • LinkedList: Linked list structure, slow query, fast addition and deletion, thread unsafe, so high efficiency.

 addFirst()    removeFirst()    getFirst()
  • Set :"Features:" The access is unordered, the element has no index, and the element cannot be repeated.

  • HashSet : The storage is unordered, the elements have no index, and the elements cannot be repeated. The bottom layer is a hash table.

Excuse me: How does the hash table ensure that the elements are unique? The bottom layer relies on the hashCode and equals methods.

When storing an element, first calculate an index based on hashCode + array length to determine whether there is an element at the index position.

If there are no elements, store them directly. If there are elements, first judge the equals method to compare whether the two elements are the same. If they are different, store them, and if they are the same, discard them.

The elements of our custom object storage must implement hashCode and equals.

  • LinkedHashSet : Stored in order, elements cannot be repeated.

  • TreeSet : Access is unordered, but it can be sorted (natural sorting), and elements cannot be repeated.

There are two sorting methods:

  • Natural ordering :

Our element must implement the Comparable interface. Comparable. Implement the CompareTo method.

  • Comparator sort :

We need a custom class that implements the Comparetor interface, which is the comparator that implements the compare method.

Then when creating the TreeSet, pass the comparator object as a parameter to the TreeSet.

Map:

Map is a two-column collection, which stores key-value pairs, the keys are required to be unique, and the values ​​can be repeated

There is a one-to-one correspondence between key and value, and a key can only correspond to one value

**Map features: ** is unordered access, keys cannot be repeated

When Map is stored, the key value is passed into the Entry, and then the Entry object is stored

Among them below areHashMap,LinkedHashMap和TreeMap

HashMap:

It is implemented based on the hash table structure, so when storing custom objects as keys, the hasCode and equals methods must be rewritten. access disorder

The following demonstrates a HashMap with custom objects as keys:

package  好好学java;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        // 利用HashMap存储,自定义对象Person作为键
        // 为了保证键的唯一性,必须重写hashCode和equals方法
        HashMap<Person,String> map = new HashMap<Person,String>();
        
        map.put(new Person("cy", 12), "JAVA");
        map.put(new Person("李四", 13), "IOS");
        map.put(new Person("小花", 22), "JS");
        map.put(new Person("sihai", 32), "PHP");
        map.put(new Person("cy", 12), "C++");
        
        Set<Entry<Person, String>> entrySet = map.entrySet();
        Iterator<Entry<Person, String>> it = entrySet.iterator();
        while (it.hasNext()){
            Entry<Person, String> entry = it.next();
            System.out.println(entry.getKey() + "---" + entry.getValue());
        }
        // 结果:存入的时候添加了两个cy,如果Map中键相同的时候,当后面的值会覆盖掉前面的值
        /*
        Person [name=李四, age=13]---IOS
        Person [name=cy, age=12]---C++
        Person [name=sihai, age=32]---PHP
        Person [name=小花, age=22]---JS
        */

        
    }
    

}

 

LinkedHashMap:

The usage is basically the same as HashMap. It is based on the linked list and hash table structure, so it has the characteristics of orderly access and non-repetitive keys.

The following demonstration uses LinkedHashMap storage, note that the order of storage is consistent with the order of traversal:

package  好好学java;

import java.util.LinkedHashMap;
import java.util.Map.Entry;

public class Test {
    public static void main(String[] args) {
        // 利用LinkedHashMap存储,自定义对象Person作为键
        // 为了保证键的唯一性,必须重写hashCode和equals方法
        LinkedHashMap<Person,String> map = new LinkedHashMap<Person,String>();
        
        map.put(new Person("cy", 12), "JAVA");
        map.put(new Person("李四", 13), "IOS");
        map.put(new Person("小花", 22), "JS");
        map.put(new Person("sihai", 32), "PHP");
        map.put(new Person("cy", 12), "C++");
        
        // foreach遍历
        for (Entry<Person,String> entry : map.entrySet()){
            System.out.println(entry.getKey()+"==="+entry.getValue());
        }
        // 结果:存入的时候添加了两个cy,如果Map中键相同的时候,当后面的值会覆盖掉前面的值
        // 注意:LinkedHashMap的特点就是存取有序,取出来的顺序就是和存入的顺序保持一致
        /*
        Person [name=cy, age=12]===C++
        Person [name=李四, age=13]===IOS
        Person [name=小花, age=22]===JS
        Person [name=sihai, age=32]===PHP
        */
    }
}

 

TreeMap:

Save the custom object in the TreeMap collection, and use the custom object as the key value of the TreeMap collection. Due to the binary tree used at the bottom of TreeMap, all the data stored in it needs to be sorted. To sort, the object is required to have a comparison function. The class to which the object belongs needs to implement the Comparable interface. Or pass a Comparator interface object to the TreeMap collection.

Use TreeMap to store custom objects as keys:

package  好好学java;

import java.util.Comparator;
import java.util.Map.Entry;
import java.util.TreeMap;

public class Test {
    public static void main(String[] args) {
        // 利用TreeMap存储,自定义对象Person作为键
        // 自定义对象实现Comparable接口或者传入Comparator比较器
        TreeMap<Person,String> map = new TreeMap<Person,String>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                if (o1 == o2){
                    return 0;
                }
                int result = o1.getAge() - o2.getAge();
                if (result == 0){
                    return o1.getName().compareTo(o2.getName());
                }
                return result;
            }
        });
        
        map.put(new Person("cy", 12), "JAVA");
        map.put(new Person("李四", 50), "IOS");
        map.put(new Person("小花", 32), "JS");
        map.put(new Person("sihai", 32), "PHP");
        map.put(new Person("cy", 12), "C++");
        
        // foreach遍历
        for (Entry<Person,String> entry : map.entrySet()){
            System.out.println(entry.getKey()+"==="+entry.getValue());
        }
        // 结果:存入的时候添加了两个cy,如果Map中键相同的时候,当后面的值会覆盖掉前面的值
        // 注意:TreeMap 取出来的顺序是经过排序的,是根据compara方法排序的
        /*
        Person [name=cy, age=12]===C++
        Person [name=小花, age=32]===JS
        Person [name=sihai, age=32]===PHP
        Person [name=李四, age=50]===IOS
        */
    }
}

If there is something inappropriate in the article, please correct me. You can also pay attention to my WeChat public account: 好好学java, get high-quality learning resources, or join the QQ technical exchange group: 766946816, let's talk about java.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325261571&siteId=291194637
Recommended