详解Java中的Collection单列集合(从底层到用法超详细解析和细节分析)

news2024/10/2 17:33:54

⭕在 Java 中,集合框架是开发过程中最常用的数据结构之一,其中 Collection 接口是整个集合框架的基础。Collection 是处理单列数据的接口,它定义了一些通用的操作,允许对一组对象进行操作。今天我们将深入介绍 Java 中的单列集合 Collection 接口,以及它的常见子接口和实现类。

在谈论集合时,我们都有一个问题,那就是数组和集合有什么区别?

相同点

  • 集合和数组都是容器,可以用来存储多个数据

不同点

  • 数组长度是不可变的,集合的长度是可以变的

  • 集合只能存储引用数据类型,如果要存储基本数据类型,需要存对应的包装类

  • 集合中集成了很多实用的数据处理方法,提供了功能各异的集合以达到提高程序运行效率的目的

想要深入了解Collection集合,我们就得先了解其在整个集合类的体系结构中的位置


一、集合体系结构图(Collection在集合体系中的位置)


二、创建Colletion对象的方式

由集合体系结构图可知Collection类是单列集合的顶层接口,所以不能通过它直接创建对象,我们需要用到其子接口的实现类或者通过多态的方式创建其对象。

2.1 多态的方式

2.2 具体实现类


三、Collection 核心(常用)方法

方法名称返回类型描述
boolean add(E e)boolean向集合中添加元素。如果集合因为此调用发生了变化,则返回 true
boolean remove(Object o)boolean从集合中删除指定元素。如果集合包含该元素并成功移除,则返回 true
boolean contains(Object o)boolean判断集合中是否包含指定的元素。如果集合包含此元素,则返回 true
int size()int返回集合中元素的数量。
Iterator<E> iterator()Iterator<E>返回一个用于遍历集合中元素的迭代器。
void clear()void清空集合中的所有元素。
boolean isEmpty()boolean判断集合是否为空。如果集合为空,则返回 true

3.1 add方法

向集合中添加元素。如果集合因为此调用发生了变化,则返回 true

细节:

  • 如果往List系列集合中添加元素永远返回true,因为List系列集合元素可重复
  • 如果往List系列集合中添加元素如果元素已经存在,则会返回false

3.2 remove方法

从集合中删除指定元素。如果集合包含该元素并成功移除,则返回 true,如果元素不存在则返回false

细节:因为Collection里面定义的是共性的方法(Set系列集合也要适用),所以此时不能通过索引进行删除,这里面具体涉及多态中方法重写和重载的区别,可以参考我另外一篇文章

在多态的方法调用中为什么会出现“左边编译左边运行”的现象icon-default.png?t=O83Ahttps://blog.csdn.net/q251932440/article/details/142509834?spm=1001.2014.3001.5501

3.3 clear方法

清空集合中的所有元素。

3.4 contains方法

细节:contains方法依赖equals方法进行判断,所以如果集合中存储自定义对象时,需要在JavaBean类中重写equals方法。

Student中重写的equals方法:

3.5 size方法

返回集合中元素的数量。

3.6 isEmpty方法

判断集合是否为空。如果集合为空,则返回 true

3.7 iterator方法

返回一个用于遍历集合中元素的迭代器。(在下文迭代器中介绍)


四、Collection集合的遍历

Collection集合中通用的遍历方法有三种(均不依赖索引):

  • 迭代器遍历
  • 增强for遍历
  • Lambda表达式遍历

4.1 迭代器遍历

迭代器:是集合专门用来遍历的工具。

在源码中可以看到,迭代器Iterator是一个接口类,所以不能直接创建其对象来使用,需要通过集合对象中的iterator()方法返回一个Iterator接口实现类的对象

1. 接口无法直接创建对象

接口无法直接实例化是因为它没有实现方法的具体细节。接口只是一个契约,定义了类必须实现的方法。比如,Iterator 接口定义了 hasNext()next()remove() 方法,但并没有提供这些方法的具体实现。

2. ArrayListiterator() 方法

当你调用 ArrayListiterator() 方法时,它内部实际上是返回了一个 匿名内部类具体的类 的实例,这个实例实现了 Iterator 接口。也就是说,虽然我们只看到了 Iterator 接口,但它实际是 ArrayList 内部某个私有类的对象,该类实现了 Iterator 接口的所有方法。

ArrayList 源代码中,iterator() 方法大概像这样实现:

public Iterator<E> iterator() {
    return new Itr();  // 返回一个实现了 Iterator 接口的类的实例
}

private class Itr implements Iterator<E> {
    // 实现 Iterator 接口的方法,如 hasNext(), next(), remove()
    public boolean hasNext() {
        // 具体实现
    }

    public E next() {
        // 具体实现
    }

    public void remove() {
        // 具体实现
    }
}

4.1.1 迭代器(Iterator)常用方法表格

方法名称返回类型描述
boolean hasNext()boolean判断集合中是否还有下一个元素。如果有,返回 true;否则返回 false。通常用于循环控制。
E next()E返回集合中的下一个元素,并将迭代器的指针移动到下一个元素。如果已经没有元素可返回,调用该方法会抛出 NoSuchElementException 异常。
void remove()void移除迭代器当前指向的元素(即最近一次调用 next() 方法返回的元素)。这是可选操作,如果集合不支持 remove() 方法,调用时会抛出异常。

4.1.2 示例1-遍历:

细节:迭代遍历结束后,指针不会复位,如果还想遍历则要新建一个迭代器

4.1.3 示例2-遍历的过程中删除元素

移除迭代器当前指向的元素(即最近一次调用 next() 方法返回的元素

如果要删除,用迭代器的remove方法,如果用集合的方法进行增加或者删除会报错

正确用法:

4.1.4 迭代器使用的注意点

  • 迭代器遍历完毕后,指针不会复位,如果还要继续遍历,需要新建一个迭代器
  • 指针处已经没有元素仍要执行next方法,系统会报错 'NoSuchElementException' (空元素异常)
  • 循环中,只能使用一次next方法,如果在一个循环中多次调用next方法,元素总数为奇数的时候也会有 'NoSuchElementException' (空元素异常)报错的风险
  • 迭代遍历的过程中(循环里)不能用集合的方法进行增删改查
  • 数组不能直接使用迭代器进行遍历,需要使用需转换为集合

4.2 增强for遍历

  • 增强for于JDK5后问世,其内部原理是一个Iterator迭代器
  • 所有单列集合和数组才能使用增强for进行遍历

作用:简化数组和集合的遍历,增加安全性

格式:

for(集合/数组中元素的数据类型 变量名 : 集合/数组名) {

// 已经将当前遍历到的元素封装到变量中了,直接使用变量即可

}

快捷:集合/数组.for 回车——自动生成增强for代码块

4.2.1 示例:

4.2.2 增强for注意点

增强for里面的Student student是一个第三方变量,student是其变量名,改变该变量值,不会影响集合中的数据

验证:

4.3 Lambda表达式遍历

利用forEach方法,结合Lambda表达式进行遍历(其底层是增强for)

作用:简化代码

4.3.1 示例:

使用forEach后,使用Lambda表达式前:

使用Lambda表达式后:

4.3.2 使用剖析 

通过查看源码可以知道,forEach方法需要传入的形参是一个Consumer接口类型的数据,而且是一个函数式接口。所以我们在传入参数的时候需要传入一个Consumer接口的实现类对象,因此采用了匿名内部类的方式创建其实现类对象并传入到方法中,然后根据Lambda表达式格式改写成Lambda表达式以简化代码。

4.3.3 注意:

修改student一样不会改变集合的值,和增强for一样(因为底层就是一个增强for)

4.4 三种遍历方法的使用场景


五、Collection子接口——List集合

5.1 List集合的特点

  • 存取有序(指的是存和取得顺序一样,跟排序不同
  • 可以重复
  • 有索引

List继承了Collection,但List仍然是一个接口类,如果想要创建List集合,则需要创建List接口得实现类对象 (ArrayList、LinkedList),例如:

5.2 List集合的特有方法

  • List继承了Collection,拥有Collection集合的所有方法
  • 因为List集合支持索引,索引新增了一些处理索引的方法方法介绍

方法列表:

方法名描述
void add(int index,E element)在此集合中的指定位置插入指定的元素
E remove(int index)删除指定索引处的元素,返回被删除的元素
E set(int index,E element)修改指定索引处的元素,返回被修改的元素
E get(int index)返回指定索引处的元素

5.2.1 add方法

在List集合中有两种add方法:

  • Collection中的add
  • void add(int index,E element)  在此集合中的指定位置插入指定的元素

这里重点分析第二种

代码示例:

打印结果:

由上述代码可知,使用add指定添加索引后,原本在该索引的元素会往后退一位让出索引,其后面的元素都会依次往后移动

5.2.2 remove方法

List集合中remove方法也有两种:

  • Collection中的remove
  • E remove(int index)  删除指定索引处的元素,返回被删除的元素

这里仍然重点分析第二种

代码示例:

标识代码块中的打印结果:

由上述代码可知,当使用remove删除一个元素的时候,被删除所在元素的位置就会空了,其后面的元素会自动依次向前移动

细节问题

当创建一个整数类型的集合时,采用remove方法删除会使用删除索引的remove方法还是使用删除元素的remove方法?

代码演示:

如果一定要使用其删除1这个元素,就需要进行手动装箱:

5.2.3 set方法

5.2.4 get方法

5.3 List集合遍历方式及对比

5.3.1 迭代器遍历

5.3.2 列表迭代器

往前迭代那个方法有局限性,因为迭代器一开始默认实在0索引处的(基本不用)

遍历过程中添加元素:

5.3.3 增强for

5.3.4 Lambda表达式

5.3.5 普通for循环

5.4 List的实现类——LinkedList

5.4.1 底层核心步骤

  1. 刚开始创建的时候,底层创建了两个变量:一个记录头结点first,一个记录尾结点last,默认为null

  2. 添加第一个元素时,底层创建一个结点对象,first和last都记录这个结点的地址值

  3. 添加第二个元素时,底层创建一个结点对象,第一个结点会记录第二个结点的地址值,last会记录新结点的地址值

LinkedList集合底层是链表结构实现的,查询慢,增删快

5.4.2 特有方法

但是如果操作首尾元素,速度也是非常快的,所以LinkedList多了一些操作首尾元素的方法:

方法名说明
public void addFirst(E e)在该列表开头插入指定的元素
public void addLast(E e)将指定的元素追加到此列表的末尾
public E getFirst()返回此列表中的第一个元素
public E getLast()返回此列表中的最后一个元素
public E removeFirst()从此列表中删除并返回第一个元素
public E removeLast()从此列表中删除并返回最后一个元素

但是这些方法用得比较少,在Collection和List的方法中也基本能实现。

5.5 List的实现类——ArrayList

5.5.1 底层核心步骤:

  • 创建ArrayList对象的时候,他在底层先创建了一个长度为0的数组。
    • 数组名字:elementDate,定义变量size。
  • size这个变量有两层含义(添加元素,添加完毕后,size++):
    • ①:元素的个数,也就是集合的长度
    • ②:下一个元素的存入位置

当添加第一个元素的时候,底层会创建一个新的长度为10的数组

  • 扩容时机一:
    • 当存满时候,会创建一个新的数组,新数组的长度,是原来的1.5倍,也就是长度为15.再把所有的元素,全拷贝到新数组中。
    • 如果继续添加数据,这个长度为15的数组也满了,那么下次还会继续扩容,还是1.5倍。
  • 扩容时机二:
    • 如果一次添加多个元素,1.5倍放不下,那么新创建数组的长度以实际为准。

六、Collection子接口——Set集合

Set中的方法基本和Collection中的方法一致

6.1 Set集合的特点

  • 数据存取顺序不一致(LinkedHashSet除外)
  • 不可存储重复元素(可以利用这个特点来对数据去重)
    • add方法的返回值在Set中奏效了,如果重复的元素添加进集合,会添加失败并返回false
  • 没有索引(遍历时不能使用普通for)

6.1.1 Set实现类与子实现类的特点

6.2 Set集合遍历方式

与Collection一样:

  • 迭代器
  • 增强for
  • Lambda表达式

6.2.1 迭代器遍历

6.2.2 增强for

6.2.3 Lambda表达式

6.3 Set的实现类——HashSet

6.3.1 特点

  • 底层数据结构是哈希表(JDK8以后由数组+链表+红黑树组成) 
    • 默认加载因子:填充的元素达到数组长度的75%就扩容一倍
  • 存取无序
  • 不可以存储重复元素
  • 没有索引 
  • 增删改查的性能都很好

6.3.2 哈希值

JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

⭕哈希值的获取

Object类中的public int hashCode():返回对象的哈希值

⭕哈希值的特点
  • 同一个对象多次调用hashCode()方法返回的哈希值是相同的

  • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象而属性值相同的哈希值相同String等java已经定义好的对象已经重写了该方法

  • 在小部分情况下,不同属性值或者不同地址值计算出来的哈希值也有可能一样(哈希碰撞)

    • 因此为了避免哈希碰撞导致部分元素丢失,通常也要重写自定义对象(String等java已经定义好的对象已经重写了该方法)中的equals方法

      • 原因:这样一来,即使哈希值相同的元素还会被进一步被equals方法确认是否为重复元素,放防止直接被丢掉不存。

6.3.3 代码示例

学生类:
package test01;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", 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);
    }
}
测试类:
package test01;

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

public class SetTest01 {
    public static void main(String[] args) {
        Set<Student> set1 = new HashSet<>();
        Student s1 = new Student("zhangsan",11);
        Student s2 = new Student("lisi",13);
        Student s3 = new Student("wangwu",12);

        set1.add(s1);
        set1.add(s2);
        set1.add(s3);

        set1.forEach(student -> System.out.println(student));
    }
}

6.3.4 HashSet子类——LinkedHashSet

LinkedHashSet与HashSet不同的是:LinkedHashSet集合存取元素是有序的

为什么存取有序?

LinkedHashSet其底层数据结构依然是哈希表,只是每个元素又额外增加了一个双链表机制记录存储的顺序。

通过以下代码展示,我们可以知道LinkedHashSet集合存取元素是有序的

如果以后数据要去重,我们使用哪一个集合?

6.4 Set的实现类——TreeSet

6.4.1 特点

  • 可以将元素按照规则排序(以下必选其一,不然获取集合会报错)
    • 实现Comparable接口进行自然排序
    • 使用比较排序器Comparator
  • 不可存储重复元素(依赖上述两种比较方法实现的,因此不需要类重写HashCode和equals方法
  • 没有索引
  • 底层数据结构为红黑树

6.4.2 在没有排序时的TreeSet集合:

当我们添加自定义对象进集合后,TreeSet不知道排序规则,会出现如下报错(类转换异常

如果我们添加整数类型的对象进TreeSet中,会得到以下结果,其数据从小到大排列起来了

那为什么会出现这种状况呢?TreeSet的排序规则是什么呢?

6.4.3 TreeSet的默认排序规则

TreeSet的排序都是要实现Comparable接口进行自然排序或者使用比较排序器Comparator来进行的,之所以java中的一些定义好的数据类如Integer、String等能够直接排序(有默认排序规则)是因为java已经在这些类上实现了Comparable接口。

Integer源码

  • 对于数值类型(如Integer、Double):默认按照从小到大顺序进行排序
  • 对于字符、字符串类型:按照字符在ASCII码表中的数字升序进行排序(从小到大)
    • 剖析字符串排序:
  • 自定义对象,需要实现Comparable接口进行自然排序或者使用比较排序器Comparator

那么接下来我们就开始介绍这两种排序方法。

6.4.4 TreeSet的排序方法

⭕自然排序Comparable接口的使用 
实现步骤
  1. 使用空参构造创建TreeSet集合

    用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
  2. 自定义的Student类实现Comparable接口

    自然排序,就是让元素所属的类实现Comparable接口,指定要对比的类型,重写compareTo(T o)方法
  3. 重写接口中的compareTo方法(指定排序规则

    重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
代码示例:
  • 存储学生对象并遍历,创建TreeSet集合使用无参构造方法

  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

学生类:

package test01;

import java.util.Objects;

public class Student implements Comparable<Student>{
    private String name;
    private int age;

    public Student() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }

    @Override
    public int compareTo(Student o) {
        //大于0说明this.age大,排在后面
        int result = this.age - o.age;
        //this.name.compareTo(o.name),因为this.name是一个字符串对象
        //调用字符串对象可以用到字符串类型中定义好的compareTo方法
        result = result == 0 ? this.name.compareTo(o.name) : result;
        return result;
    }
}

测试类:

package test01;

import java.util.Set;
import java.util.TreeSet;

public class TreeSetTest01 {
    public static void main(String[] args) {
        Set<Student> t1 = new TreeSet<>();
        Student s1 = new Student("zhangsan",11);
        Student s2 = new Student("lisi",13);
        Student s3 = new Student("wangwu",11);
        Student s4 = new Student("linchuqiao",21);

        t1.add(s1);
        t1.add(s2);
        t1.add(s3);
        t1.add(s4);

        for (Student s : t1) {
            System.out.println(s);
        }
    }
}

运行结果:

⭕比较排序器Comparator的使用

Comparator也是一个接口,但是需要在带参构造方法使用

实现步骤
  • 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的

  • 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法

  • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

代码示例:

要修改默认排序,先对字符串长度排序

package test01;

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

public class TreeSetTest02 {
    public static void main(String[] args) {
        Set<String> set = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int result = o1.length() - o2.length();
                return result == 0 ? o1.compareTo(o2) : result;
            }
        });

        set.add("guangzhou");
        set.add("chongqing");
        set.add("beijing");
        set.add("shanghai");

        for (String s : set) {
            System.out.println(s);
        }
    }
}

运行结果:

String原先实现了Comparable接口,但是为了修改默认排序采用了Comparator比较器,由此可知第二种和第一种方法同时存在的话会遵循第二种方法(Comparator比较器)。

⭕两种排序方法总结
  • 自然排序: 自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序

  • 比较器排序: 创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序

  • 在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,必须使用比较器排序(一般是需要修改已经在源码中写好的排序规则,如String等类型的对象

两种方式中关于返回值的规则:

  • 如果返回值为负数,表示当前存入的元素是较小值,存左边

  • 如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存

  • 如果返回值为正数,表示当前存入的元素是较大值,存右边


七、全文总结

Collection 接口及其子接口 ListSet 构成了 Java 集合框架的核心部分,它们通过不同的实现类为我们提供了灵活的方式来处理数据。理解各个集合类的特点和适用场景,能够帮助开发者高效地组织和操作数据。

7.1 Collection集合性能对比总结

操作ArrayListLinkedListHashSetTreeSet
添加元素较快较快(首尾)较慢(排序)
删除元素较慢较快(首尾)较慢
查找元素较慢(首尾快)较慢
元素存取顺序有序有序无序可排序

在实际开发中,选择合适的集合类是非常重要的。对于需要频繁查找、插入和删除的场景,应根据数据结构的特点选择合适的实现类。

通过本文的介绍,你应该能够初步掌握 Java 中 Collection 单列集合的基础知识,并且学会如何选择适合的集合类进行开发。在实际项目中,合理使用集合将有助于提升代码的性能和可维护性噢!~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2184789.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ECharts图表图例4

jave 用eclipse软件 代码&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <!-- 引入ECharts脚本 --> <script src"js/echarts.js"></script> <title>绘制堆积面积图</title&g…

Unraid的cache使用btrfs或zfs?

Unraid的cache使用btrfs或zfs&#xff1f; 背景&#xff1a;由于在unraid中添加了多个docker和虚拟机&#xff0c;因此会一直访问硬盘。然而&#xff0c;单个硬盘实在难以让人放心。在阵列盘中&#xff0c;可以通过添加校验盘进行数据保护&#xff0c;在cache中无法使用xfs格式…

Leecode热题100-283.移动零

给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]示例 2: 输入: nums [0] 输出: […

【Python报错已解决】ImportError: No module named ‘module‘

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

单目操作符、--、++和do-while循环

昨天我们算术操作符的除法和乘法&#xff0c;以及引入while和for循环&#xff0c;今天我们来看新的内容。 借助我们之前写的计算器代码来深入学习一下其他东西。 单目操作符——、--、& 除了昨天说的那些操作符之外&#xff0c;记不记得输入函数中有一个&这么一个符…

分散加载文件 scatter files

目录 一、加载域和执行域二、Image entry points三、映射符号四、链接器预定义符号1、将符号引入到程序中1.1 引入到 C/C1.2 引入到汇编 2、域相关的符号2.1 执行域符号 Image$$2.2 执行域符号 Load$$2.3 加载域符号 Load$$LR$$2.4 节相关的符号2.5 镜像符号2.6 输入节符号 五、…

HarmonyOS鸿蒙 Next 实现协调布局效果

HarmonyOS鸿蒙 Next 实现协调布局效果 ​ 假期愉快! 最近大A 的涨势实在是红的让人晕头转向&#xff0c;不知道各位收益如何&#xff0c;这会是在路上&#xff0c;还是已经到目的地了? 言归正传&#xff0c;最近有些忙&#xff0c;关于鸿蒙的实践系列有些脱节了&#xff0c;…

Electron 是如何工作的

1. 创建electron项目 pnpm init pnpm add -D electron修改配置项 package.json {"name": "electron-menu","version": "1.0.0","description": "","main": "main.js", // eletron入口&quo…

【重学 MySQL】四十七、表的操作技巧——修改、重命名、删除与清空

【重学 MySQL】四十七、表的操作技巧——修改、重命名、删除与清空 修改表添加字段语法示例注意事项 删除字段语法示例 修改字段使用 MODIFY COLUMN语法示例 使用 CHANGE COLUMN语法示例 重命名表语法示例 删除表语法示例 清空表使用 TRUNCATE TABLE使用 DELETE FROM对比 TRUNC…

聊聊晶圆厂中的常见口语(1)

知识星球里的学员问&#xff1a;半导体公司的工程师总爱用一些英语代替中文&#xff0c;比如care,show&#xff0c;用这种简单的单词代替中文&#xff0c;能不能给我们总结工程师常用的英语单词&#xff0c;比较口语化的&#xff01; 为什么晶圆厂会用很多英文口语&#xff1f…

华为---以太网静态路由配置使用下一跳通信正常,而使用出接口无法通信

目录 1. 实验环境 2. 结果测试 3. 分析验证 3.1 以太网静态路由配置使用下一跳跨网段通信抓包分析 3.2 以太网静态路由配置使用出接口跨网段通信抓包分析 3.3 以太网静态路由配置使用出接口无法跨网段通信问题解决办法 1. 实验环境 以太网静态路由配置使用下一跳跨网段通…

番茄成熟度检测系统源码分享

番茄成熟度检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer V…

Opencv第十一章——视频处理

1. 读取并显示摄像头视频 1.1 VideoCapture类 VideoCapture类提供了构造方法VideoCapture(),用于完成摄像头的初始化工作&#xff0c;其语法格式如下&#xff1a; capture cv2.VideoCapture(index) 参数说明&#xff1a; capture:要打开的摄像头视频。 index:摄像头设备索引。…

【区间dp】AT_dp_l 题解

题意 给一个双端队列&#xff0c;双方轮流取数&#xff0c;每一次能且只能从队头或队尾取数&#xff0c;取完数后将这个数从队列中弹出。双方都希望自己取的所有数之和尽量大&#xff0c;且双方都以最优策略行动&#xff0c;假设先手取的所有数之和为 X X X&#xff0c;后手取…

【Git】一文看懂Git

Git 一、简介1. Git 与 SVN 区别1.1 Git 是分布式的&#xff0c;SVN 不是1.1.1 分布式版本控制系统Git1.1.2 集中式版本控制系统SVN 1.2 Git 把内容按元数据方式存储&#xff0c;而 SVN 是按文件1.3 Git 分支和 SVN 的分支不同1.4 Git 没有一个全局的版本号&#xff0c;而 SVN …

五.运输层

目录 5.1概述 5.2传输层的寻址与端口 熟知端口号 套接字(Socket) 5.3 UDP 特点 UDP报文格式 UDP校验 二进制反码求和 5.4 TCP 特点 可靠传输 停止等待协议 流水线方式 累计应答 流量控制 滑动窗口 拥塞控制 三次握手&#xff0c;四次握手 5.1概述 只有主机…

Pikachu-Cross-Site Scripting-反射型xss(get)

存储型XSS 存储型XSS是指恶意脚本被存储在目标服务器上&#xff0c;当用户访问包含该脚本的页面时&#xff0c;脚本会被执行。攻击者通常通过输入框、留言板等用户可输入的地方进行注入。例如&#xff0c;攻击者可以在留言板中输入恶意脚本&#xff0c;当其他用户查看留言时&a…

3.基于分数的生成模型

1.简介 基于分数的生成模型(SGM)的核心是Stein分数(或分数函数)。给定一个概率密度函数p(x)&#xff0c;其分数函数定义为对数概率密度的梯度Vxlogp(x)。生成模型通过学习并建模输入数据的分布&#xff0c;从而采集生成新的样木&#xff0c;该模型广泛运用于图片视频生成、文本…

假期惊喜,收到公司款项86167.14元

假期惊喜 近日&#xff0c;有网友爆料称&#xff0c;比亚迪在未提前通知员工的情况下&#xff0c;突然发放了利润奖金。 有人获得了七八万元&#xff0c;也有人拿到了十多万元。 一位比亚迪员工的帖子显示&#xff0c;在9月26日下午&#xff0c;他的银行卡突然收到一笔 86167.1…

数字化那点事:一文读懂数字孪生

一、数字孪生的定义 数字孪生&#xff08;Digital Twin&#xff09;是指通过数字技术构建的物理实体的虚拟模型&#xff0c;能够对该实体进行全方位、动态跟踪和仿真预测。简单来说&#xff0c;数字孪生就是在一个设备或系统的基础上创造一个数字版的“克隆体”&#xff0c;这…