JAVA Foundation-Chapter 13 List, Set, Data Structure, Collections

main content

data structure

List集合
Set集合
Collections

teaching objectives

能够说出List集合特点
能够说出常见的数据结构
能够说出数组结构特点
能够说出栈结构特点
能够说出队列结构特点
能够说出单向链表结构特点
能够说出Set集合的特点
能够说出哈希表的特点
使用HashSet集合存储自定义元素
能够说出可变参数的格式
能够使用集合工具类
能够使用Comparator比较器进行排序

Chapter One Data Structure

2.1 What is the use of data structure?

When you use the container classes in Java, have you ever thought about how ArrayList is like an infinitely expanding array, or like a linked list
. easy to use? Easy to use, this is the use of data structure, but you use it unknowingly.

Real-world storage, the tools and modeling we use. Each data structure has its own advantages and disadvantages. Think about it if Google’s data uses
arrays of storage, can we easily find the data we need? The algorithm, how to do the fastest insertion, search, and deletion
among so many data , is also pursuing faster.

Our java is an object-oriented language, just like an automatic car, and the C language is like a manual jeep. What about the data structure? It is the working principle of the gearbox. You
can drive an automatic car from point A to point B without knowing how the gearbox works, and it may not be slower than someone who knows. Writing programs is the
same as driving a car. Experience can play a big role, but if you don’t know how the bottom layer works, you can always drive, and neither repair nor
build a car. Of course, the data structure content is relatively large, and it is relatively time-consuming to study in detail, and it is impossible to achieve overnight. We will introduce common data
structures: stacks, queues, arrays, linked lists, and red-black trees. As an introduction to data structures, just understand their characteristics
.

2.2 Common data structures

Common structures for data storage are: stacks, queues, arrays, linked lists, and red-black trees. Let's take a look separately:

Stack

栈:stack,又称堆栈,它是运算受限的线性表,其限制是仅允许在标的一端进行插入和删除操作,不允许在其
他任何位置进行添加、查找、删除等操作。

Simply put: using the structure of the collection, access to elements has the following characteristics

先进后出(即,存进去的元素,要在后它后面的元素依次取出后,才能取出该元素)。例如,子弹压进弹
夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能弹出下面的
子弹。
栈的入口、出口的都是栈的顶端位置。

Here are two nouns that need attention:

Pushing the stack: It means storing elements. That is, the element is stored at the top position of the stack, and the existing elements in the stack move one position to the bottom of the stack in turn.

Pop the stack: just take the element. That is, the element at the top position of the stack is taken out, and the existing elements in the stack move one position to the top of the stack in turn.

queue

队列:queue,简称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,
而在表的另一端进行删除。

Simply put, using this structured set, access to elements has the following characteristics:

先进先出(即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素)。例如,小火车过山
洞,车头先进去,车尾后进去;车头先出来,车尾后出来。

The entrance and exit of the queue each occupy one side. For example, in the figure below, the left side is the entrance and the right side is the exit.

Array

数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。就像是一排出
租屋,有 100 个房间,从 001 到 100 每个房间都有固定编号,通过编号就可以快速找到租房子的人。

Simply put, using this structured collection, access to elements has the following characteristics:

查找元素快:通过索引,可以快速访问指定位置的元素

Adding and deleting elements is slow

Add element at specified index position: need to create a new array, store the specified new element at the specified index position, and then root the original array element

According to the index, copy to the corresponding index position of the new array. As shown below

Specify the index position to delete the element: a new array needs to be created, and the original array element is copied to the position corresponding to the index of the new array according to the index

The element at the specified index position in the original array is not copied to the new array. As shown below

Linked list

链表:linked list,由一系列结点node(链表中每一个元素称为结点)组成,结点可以在运行时i动态生成。每
个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。我们常说的
链表结构有单向链表与双向链表,那么这里给大家介绍的是单向链表。

Simply put, using this structured set, access to elements has the following characteristics:

Multiple nodes are connected through addresses. For example, if multiple people hold hands, each person uses their right hand to hold the individual's left hand, in turn

By analogy, multiple people are connected together.

Slow searching for elements: To find an element, you need to go through the connected nodes and search for the specified element in turn

Fast addition and deletion of elements:

Add element: only need to modify the address of the next element.

Delete element: only need to modify the address of the next element.

Red black tree

二叉树:binary tree ,是每个结点不超过 2 的有序树(tree) 。

A simple understanding is a structure similar to the tree in our lives, except that each node can have at most two child nodes.

A binary tree is a tree structure with at most two subtrees per node. The top node is called the root node, and the two sides are called "left subtree" and "right subtree".

As shown:

What we are talking about is a more interesting binary tree called a red-black tree. The red-black tree itself is a binary search tree. After inserting a node, the tree is still

It is a binary search tree. This means that the key values ​​of the tree are still in order.

Red-black tree constraints:

1. Nodes can be red or black

2. The root node is black

3. Leaf nodes (especially empty nodes) are black

4. The child nodes of each red node are black

5. The number of black nodes on all paths from any node to each leaf node is the same

Features of red-black trees:

The speed is extremely fast, approaching the balanced tree, and the minimum and maximum number of leaf elements is not more than twice

Chapter 2 List Collection

After we have mastered the use of the Collection interface, let's take a look at the subclasses in the Collection interface. What characteristics do they have?

Next, let's learn several commonly used subclasses in Collection (java.util.List collection, java.util.Set collection).

1.1 Introduction to List interface

The java.util.List interface inherits from the Collection interface and is an important branch of the single-column collection. It is customary to
call the objects that implement the List interface the List collection. Duplicate elements are allowed in the List collection. All elements are stored in a linear manner
. The specified element in the collection can be accessed by index in the program . In addition, another feature of the List collection is that the elements are ordered, that is, the order in which the elements are stored and taken out are the same.

After reading the API, let's summarize:

List interface features:

1. 它是一个元素存取有序的集合。例如,存元素的顺序是 11 、 22 、 33 。那么集合中,元素的存储就是按照 11 、
22 、 33 的顺序完成的)。

2. It is a collection with an index, and the elements in the collection can be accurately manipulated through the index (the same reason as the index of the array).

3. 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。
tips:我们在基础班的时候已经学习过List接口的子类java.util.ArrayList类,该类中的方法都是来自List中定
义。

1.2 Common methods in the List interface

As a sub-interface of the Collection collection, List not only inherits all the methods in the Collection interface, but also adds some
unique methods for operating the collection based on the element index , as follows:

public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
public E get(int index):返回集合中指定位置的元素。
public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。

The unique methods of the List collection are all related to the index. We have learned it in the basic class, so let's review it again:

public^ class^ ListDemo {
public static void main(String[] args) {
// 创建List集合对象
List<String> list = new ArrayList<String>();
// 往 尾部添加 指定元素
list.add("图图");
list.add("小美");
list.add("不高兴");
System.out.println(list);
// add(int index,String s) 往指定位置添加
list.add( 1 ,"没头脑");
System.out.println(list);
// String remove(int index) 删除指定位置元素 返回被删除元素
// 删除索引位置为 2 的元素
System.out.println("删除索引位置为 2 的元素");
System.out.println(list.remove( 2 ));
System.out.println(list);
// String set(int index,String s)
// 在指定位置 进行 元素替代(改)
// 修改指定位置元素
list.set( 0 , "三毛");
System.out.println(list);
// String get(int index)  获取指定位置元素
// 跟size() 方法一起用 来 遍历的
for(int i =  0 ;i<list.size();i++){
System.out.println(list.get(i));
}
//还可以使用增强for
for (String string : list) {

Chapter 3 Subclasses of List

3.1 ArrayList collection

The structure of java.util.ArrayList collection data storage is an array structure. Adding and deleting elements is slow, and searching is fast. Since the
most commonly used functions in daily development are querying data and traversing data, ArrayList is the most commonly used collection.

Many programmers use ArrayList to complete any requirements very casually during development, and are not rigorous. This usage is not recommended.

3.2 LinkedList collection

java.util.LinkedList集合数据存储的结构是链表结构。方便元素添加、删除的集合。
LinkedList是一个双向链表,那么双向链表是什么样子的呢,我们用个图了解下

In actual development, the addition and deletion of a collection element often involves first and last operations, and LinkedList provides a large number of first and last operations.
We can understand these methods as:

public void addFirst(E e):将指定元素插入此列表的开头。
public void addLast(E e):将指定元素添加到此列表的结尾。
public E getFirst():返回此列表的第一个元素。
public E getLast():返回此列表的最后一个元素。
public E removeFirst():移除并返回此列表的第一个元素。
public E removeLast():移除并返回此列表的最后一个元素。
public E pop():从此列表所表示的堆栈处弹出一个元素。
public void push(E e):将元素推入此列表所表示的堆栈。
public boolean isEmpty():如果列表不包含元素,则返回true。
for (String string : list) {
System.out.println(string);
}  
}
}

LinkedList is a subclass of List. The methods LinkedList in List are all available. We will not introduce them in detail here. We only need to understand
the unique methods of LinkedList . During development, the LinkedList collection can also be used as a stack or queue structure. (Just understand)

Method demonstration:

Chapter 4 Set Interface

java.util.Set java.util.List interfaces and interfaces, same as inherited from the Collection interface, which interfaces with the Collection of party
basically the same method, and no expansion of the Collection interface function, but more stringent than the Collection interface . Unlike the List interface
, the elements in the Set interface are disordered, and certain rules are used to ensure that the stored elements do not repeat.

Set集合有多个子类,这里我们介绍其中的java.util.HashSet、java.util.LinkedHashSet这两个集合。
tips:Set集合取出元素的方式可以采用:迭代器、增强for。

3.1 Introduction to HashSet collection

java.util.HashSet is an implementation class of the Set interface. The elements it stores are not repeatable, and the elements are all disordered (that is, the access sequence is
inconsistent). The underlying implementation of java.util.HashSet is actually a java.util.HashMap support. Since we haven't learned it yet, let's
solve it first .

HashSet determines the storage location of the element in the collection according to the hash value of the object, so it has good access and search performance.
The way to ensure the uniqueness of the element depends on the hashCode and equals methods.

Let's first use Set collection storage, look at the phenomenon, and then explain the principle:

public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<String> link = new LinkedList<String>();
//添加元素
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
System.out.println(link);
// 获取元素
System.out.println(link.getFirst());
System.out.println(link.getLast());
// 删除元素
System.out.println(link.removeFirst());
System.out.println(link.removeLast());
while (!link.isEmpty()) { //判断集合是否为空
System.out.println(link.pop()); //弹出集合中的栈顶元素
        }
System.out.println(link);
    }
}
public class HashSetDemo {
public static void main(String[] args) {
//创建 Set集合

The output is as follows, indicating that duplicate elements cannot be stored in the collection:

tips:根据结果我们发现字符串"cba"只存储了一个,也就是说重复的元素set集合不存储。

2.2 HashSet collection storage data structure (hash table)

What is a hash table?

Before JDK 1.8, the bottom layer of the hash table was implemented by array + linked list, that is, the linked list was used to handle conflicts, and the linked lists of the same hash value were stored in a linked list.
But when there are many elements in a bucket, that is, when there are many elements with equal hash values, the efficiency of searching sequentially by key value is low. In JDK1.8, hash
table storage is realized by array + linked list + red-black tree. When the length of the linked list exceeds the threshold (8), the linked list is converted to a red-black tree, which greatly reduces the search
time.

Simply put, the hash table is implemented by an array + linked list + red-black tree (JDK1.8 adds the red-black tree part), as shown in the figure below.

When you see this picture, someone has to ask, how is this stored?

In order to facilitate everyone's understanding, let's explain with a storage flowchart:

HashSet<String> set = new HashSet<String>();
//添加元素
set.add(new String("cba"));
set.add("abc");
set.add("bac");
set.add("cba");  
//遍历
for (String name : set) {
System.out.println(name);
        }
    }
}
cba
abc
bac

All in all, the introduction of red-black trees in JDK1.8 greatly optimizes the performance of HashMap, so for us to ensure the uniqueness of the HashSet collection elements is
actually determined according to the object's hashCode and equals methods. If we store a custom object in the collection, to ensure its uniqueness,
we must override the hashCode and equals methods to establish a comparison method belonging to the current object.

2.3 HashSet stores custom type elements

When storing custom type elements in HashSet, you need to rewrite the hashCode and equals methods in the object and establish your own comparison method to ensure
that the objects in the HashSet collection are unique

Create a custom student class

public^ class^ Student {
private String name;
private int age;
public Student() {

}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}

@Override
public int hashCode() {
return Objects.hash(name, age);
}
}

public class HashSetDemo2 { public static void main(String[] args) { //Create a collection object This collection stores Student type objects HashSet stuSet = new HashSet(); //Store Student stu = new Student("Yuqian", 43) ; stuSet.add(stu); stuSet.add(new Student(“郭德刚”, 44 )); stuSet.add(new Student(“于谦”, 43 )); stuSet.add(new Student(“郭麒麟”, 23 )); stuSet.add(stu);









for (Student stu2 : stuSet) {

2.3 LinkedHashSet

We know that HashSet guarantees that the elements are unique, but the elements are stored in no order, so what should we do to ensure order?

There is a subclass java.util.LinkedHashSet under HashSet, which is a data storage structure that combines a linked list and a hash table.

The demo code is as follows:

1.9 Variable parameters

After JDK1.5, if we define a method that needs to accept multiple parameters, and the multiple parameter types are the same, we can simplify it to the following format

formula:

In fact, this writing is completely equivalent to

Only the latter definition must pass the array when calling, and the former can pass data directly.

After JDK1.5. Simplified operations have appeared. … Used on parameters, called variable parameters.

System.out.println(stu2);
        }
    }
}
执行结果:
Student [name=郭德纲, age= 44 ]
Student [name=于谦, age= 43 ]
Student [name=郭麒麟, age= 23 ]
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<String>();
set.add("bbb");
set.add("aaa");
set.add("abc");
set.add("bbc");
Iterator<String> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
结果:
bbb
aaa
abc
bbc

Modifier return value type method name (parameter type... formal parameter name) {}

Modifier return value type method name (parameter type [] formal parameter name) {}

It also represents an array, but when calling this method with variable parameters, you don’t need to create an array (this is the simplicity), and directly add the elements in the array

Passed as actual parameters, in fact, the compiled class file encapsulates these elements in an array before passing it. These actions are
automatically completed when compiling the .class file.

Code demo:

tips: 上述add方法在同一个类中,只能存在一个。因为会发生调用的不确定性
注意:如果在方法书写时,这个方法拥有多参数,参数中包含可变参数,可变参数一定要写在参数列表的末
尾位置。

Chapter 5 Collections

2.1 Common functions

java.utils.Collections是集合工具类,用来对集合进行操作。部分方法如下:
public class ChangeArgs {
public static void main(String[] args) {
int[] arr = {  1 ,  4 ,  62 ,  431 ,  2  };
int sum = getSum(arr);
System.out.println(sum);
//  6  7  2 12 
// 求 这几个元素和 6  7  2 12 
int sum2 = getSum( 6 ,  7 ,  2 ,  12 ,  2121 );
System.out.println(sum2);
    }
/*
* 完成数组 所有元素的求和 原始写法
public static int getSum(int[] arr){
int sum = 0;
for(int a : arr){
sum += a;
}
return sum;
}
*/
//可变参数写法
public static int getSum(int... arr) {
int sum =  0 ;
for (int a : arr) {
sum += a;
        }
return sum;
    }
}
public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。
public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。
public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。
public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排
序。

Code demo:

After the code demonstration, we found that our collection is arranged in order, but this order is the default order, if you want to specify the order, then

How to do it?

We found that there is another method not mentioned, public static void sort(List list, Comparator<? super T>):
sort the elements in the collection according to the specified rules. Next, explain the arrangement of the specified rules.

2.2 Comparator

Let's study this method first

public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。

But this time it is a string type.

public class CollectionsDemo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
//原来写法
//list.add(12);
//list.add(14);
//list.add(15);
//list.add(1000);
//采用工具类 完成 往集合中添加元素
Collections.addAll(list,  5 ,  222 ,  1 , 2 );
System.out.println(list);
//排序方法
Collections.sort(list);
System.out.println(list);
    }
}
结果:
[ 5 ,  222 ,  1 ,  2 ]
[ 1 ,  2 ,  5 ,  222 ]

result:

We use the default rules to sort the strings, so how are the default rules defined?

Speaking of sorting, to put it simply is to compare the size between two objects, then there are two ways to compare implementation in JAVA, one is more rigid

Use java.lang.Comparable interface to achieve, one is flexible when I need to do the sorting in the selected
java.util.Comparator interface to complete.

Then the sorting done by the public static void sort(List list) method we use actually requires the type
to be sorted. It needs to implement the Comparable interface to complete the comparison function. The String type is as follows:

The String class implements this interface and completes the definition of the comparison rules, but this makes this rule hard to write. For example, if I want the string to be
sorted in descending order of the first character, then I need to modify the source code of String. This is impossible, so at this time we can use

The public static void sort(List list, Comparator<? super T>) method is completed flexibly. This involves the
Comparator interface, which is located in the java.util package. Sorting is one of the functions that the comparator can implement. This interface represents A comparator, the
comparator is comparable! As the name implies, it is sorting. In layman's terms, it is necessary to compare two objects who are ranked first and who is ranked second. Then the method of comparison is:

public int compare(String o1, String o2):比较其两个参数的顺序。
两个对象比较的结果有三种:大于,等于,小于。
如果要按照升序排序, 则o1 小于o2,返回(负数),相等返回 0 , 01 大于 02 返回(正数) 如果要按照
降序排序 则o1 小于o2,返回(正数),相等返回 0 , 01 大于 02 返回(负数)

The operation is as follows:

public class CollectionsDemo2 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("cba");
list.add("aba");
list.add("sba");
list.add("nba");
//排序方法
Collections.sort(list);
System.out.println(list);
    }
}
[aba, cba, nba, sba]
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
public class CollectionsDemo3 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("cba");
list.add("aba");
list.add("sba");
list.add("nba");
//排序方法 按照第一个单词的降序
Collections.sort(list, new Comparator<String>() {

The results are as follows:

2.3 Briefly describe the difference between Comparable and Comparator interfaces.

Comparable: Forcibly sort the objects of each class that implements it. This sorting is called the natural sorting of the class, and the compareTo method of the class
is called its natural comparison method. You can only implement compareTo() once in a class, and you cannot often modify the code of the class to achieve the sort you want. The
list of objects (and arrays) that implement this interface can be automatically sorted through Collections.sort (and Arrays.sort). The objects can be used as
keys in an ordered map or elements in an ordered set without specifying a comparator.

Comparator forcibly sort an object as a whole. Comparator can be passed to the sort method (such as Collections.sort or
Arrays.sort) to allow precise control over the sort order. You can also use Comparator to control the order of certain data structures (such as ordered sets or
ordered maps), or to provide sorting for collections of objects that do not have a natural order.

2.4 Exercise

Create a student class and store it in the ArrayList collection to complete the specified sorting operation.

Student initial class

@Override
public int compare(String o1, String o2) {
return o2.charAt( 0 ) ‐ o1.charAt( 0 );
            }
        });
System.out.println(list);
    }
}
[sba, nba, cba, aba]
public class Student{
private String name;
private int age;
public Student() {
    }
public Student(String name, int age) {
this.name = name;
this.age = age;
    }
public String getName() {
return name;
    }
public void setName(String name) {
this.name = name;
    }
public int getAge() {

Test category:

It was found that the program reported an error when we called the Collections.sort() method.

Reason: If you want the elements in the collection to be sorted, you must implement the Comparable interface.

So we have completed an implementation of the Student class, as follows:

return age;
    }
public void setAge(int age) {
this.age = age;
    }
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
    }
}
public class Demo {
public static void main(String[] args) {
// 创建四个学生对象 存储到集合中
ArrayList<Student> list = new ArrayList<Student>();
list.add(new Student("rose", 18 ));
list.add(new Student("jack", 16 ));
list.add(new Student("abc", 16 ));
list.add(new Student("ace", 17 ));
list.add(new Student("mark", 16 ));

/*

Sort students in ascending order by age

*/

//        Collections.sort(list);//要求 该list中元素类型 必须实现比较器Comparable接口
for (Student student : list) {
System.out.println(student);
        }

}

}

Test again, the code is OK and the effect is as follows:

2.5 Expansion

If you want to use independent definition rules when you use it, you can use Collections.sort (List list, Comparetor c) to define your own
rules:

effect:

If you want more rules, you can refer to the following code:

public class Student implements Comparable<Student>{
    ....
@Override
public int compareTo(Student o) {
return this.age‐o.age;//升序
    }
}
Student{name='jack', age= 16 }
Student{name='abc', age= 16 }
Student{name='mark', age= 16 }
Student{name='ace', age= 17 }
Student{name='rose', age= 18 }
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o2.getAge()‐o1.getAge();//以学生的年龄降序
    }
});
Student{name='rose', age=18}
Student{name='ace', age=17}
Student{name='jack', age=16}
Student{name='abc', age=16}
Student{name='mark', age=16}

The effect is as follows:

Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// 年龄降序
int result = o2.getAge()‐o1.getAge();//年龄降序
if(result== 0 ){//第一个规则判断完了 下一个规则 姓名的首字母 升序
result = o1.getName().charAt( 0 )‐o2.getName().charAt( 0 );
                }
return result;
            }
        });
Student{name='rose', age=18}
Student{name='ace', age=17}
Student{name='abc', age=16}
Student{name='jack', age=16}
Student{name='mark', age=16}

Guess you like

Origin blog.csdn.net/weixin_43419256/article/details/108213487