【JAVA学习笔记】53 - 集合-List类及其子类Collection、ArrayList、LinkedList类

项目代码

https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter14/src/com/yinhai/collection_

https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter14/src/com/yinhai/list_

集合

一、集合引入

        前面我们保存多个数据使用的是数组,那么数组有不足的地方,我们分析一下。

数组

        1)长度开始时必须指定,而且一旦指定,不能更改

        2)保存的必须为同类型的元素

        3)使用数组进行增加元素的示意代码-比较麻烦


写出Person数组扩容示意代码。


                Person[] pers = new Person[1];
                per[0]=new Person();

                Person[] pers2 = new Person[pers.length+ 1]; //新创建数组
                for(){} //拷贝pers数组的元素到pers2
                pers2[pers2.length-1]=new Person();//添加新的对象

集合

1)可以动态保存任意多个对象,使用比较方便!

2)提供了一系列方便的操作对象的方法: add、remove、set、 get等

3)使用集合添加,删除新元素的示意代码-简洁了

二、集合的框架体系

集合主要分两组 单列和双列

单列集合        两个重要的两个子接口List        Set

双列集合        属于双列集合,存放K-V的数据

Collection类

一、Collection类接口和常用方法

Collection接口实现类的特点

public interface Collection<E> extends iterable <E>

1) collection实现子类可以存放多个元素, 每个元素可以是bject

2)有些Collection的实现类,可以存放重复的元素,有些不可以

3)有些Collection的实现类,有些是有序的(List),有些不是有序(Set)

4) Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的
 

public class CollectionMethod {@SuppressWarnings({"all"})public static void main(String[] args) {List list = new ArrayList();//add:添加单个元素list.add("jack");list.add(10);//list.add(new Integer(10))对象list.add(true);System.out.println("list=" + list);//remove:删除指定元素//list.remove(0);//删除第一个元素list.remove(true);//指定删除某个元素System.out.println("list=" + list);//contains:查找元素是否存在System.out.println(list.contains("jack"));//T//size:获取元素个数System.out.println(list.size());//2//isEmpty:判断是否为空System.out.println(list.isEmpty());//F//clear:清空list.clear();System.out.println("list=" + list);//addAll:添加多个元素ArrayList list2 = new ArrayList();list2.add("红楼梦");list2.add("三国演义");list.addAll(list2);System.out.println("list=" + list);//containsAll:查找多个元素是否都存在System.out.println(list.containsAll(list2));//T//removeAll:删除多个元素list.add("聊斋");list.removeAll(list2);System.out.println("list=" + list);//[聊斋]}
}

二、Iterator迭代器

Collection接口遍历元素方式1-使用Iterator(迭代器)

1.基本介绍

1) Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。

2)所有实现了Collection接的集合类都有个iterator(方法, 用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。

3) Iterator的结构

4) Iterator仅用于遍历集合,Iterator 本身并不存放对象。

2.迭代器的执行原理
 

Iterator iterator = coll.iterator(): //得到一个集合的迭代器

//hasNext():判断是否还有下一个元素
        while(iterator.hasNext()){

//next(:@下移②将下移以后集合位置上的元素返回
        System.out.println(iterator.next());

                

public class CollectionIterator {@SuppressWarnings({"all"})public static void main(String[] args) {Collection col = new ArrayList();col.add(new Book("三国演义", "罗贯中", 10.1));col.add(new Book("小李飞刀", "古龙", 5.1));col.add(new Book("红楼梦", "曹雪芹", 34.6));System.out.println("col=" + col);//希望遍历该集合//1.先得到col对应的迭代器Iterator iterator = col.iterator();//2.使用while循环遍历while(iterator.hasNext()){//判断是否还有数据//返回下一个元素,类型是ObjectObject obj = iterator.next();System.out.println("obj" + obj);}//快捷键,快速的生成while循环->itit (Ctrl +J 可以显示快捷模版)////3.当退出while循环后,这是iterator迭代器指向最后的元素//iterator.next();//NoSuchElementException//4.再次遍历需要重置我们的迭代器iterator = col.iterator();}
}class Book {private String name;private String author;private double price;public Book(String name, String author, double price) {this.name = name;this.author = author;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", author='" + author + '\'' +", price=" + price +'}';}
}

 3.增强for循环完成迭代器

增强for循环,可以代替iterator迭代器, 特点:增强for就是简化版的iterator本质样。只能用于遍历合或数组。

基本语法

for(元素类型元素名:集合名或数组名) {访问元素}

public class CollectionFor {@SuppressWarnings({"all"})public static void main(String[] args) {Collection col = new ArrayList();col.add(new Book("三国演义", "罗贯中", 10.1));col.add(new Book("小李飞刀", "古龙", 5.1));col.add(new Book("红楼梦", "曹雪芹", 34.6));for (Object o : col) {System.out.println("book=" + o);}//1. 使用增强for, 在Collection集合//2. 增强for, 底层仍然是迭代器//3. 增强for可以理解成就是简化版本的 迭代器遍历//4. 快捷键方式 I// for (Object book : col) {//     System.out.println("book=" + book);// }//增强for,也可以直接在数组使用// int[] nums = {1, 8, 10, 90};// for (int i : nums) {//     System.out.println("i=" + i);// }}
}

增强for, 底层仍然是迭代器
增强for可以理解成就是简化版本的 迭代器遍历

 4.迭代器练习

public class CollectionExercise {@SuppressWarnings({"all"})public static void main(String[] args) {List list = new ArrayList();list.add(new Dog("小黑", 3));list.add(new Dog("大黄", 100));list.add(new Dog("大壮", 8));//先使用for增强for (Object dog : list) {System.out.println("dog=" + dog);}//使用迭代器System.out.println("===使用迭代器来遍历===");Iterator iterator = list.iterator();while (iterator.hasNext()) {Object dog =  iterator.next();System.out.println("dog=" + dog);}}
}
/*** 创建  3个 Dog {name, age}  对象,放入到 ArrayList 中,赋给 List 引用* 用迭代器和增强for循环两种方式来遍历* 重写Dog 的toString方法, 输出name和age*/
class Dog {private String name;private int age;public Dog(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;}@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +", age=" + age +'}';}
}

三、List接口方法

1.List接口基本介绍

        List接口是Collection接口的子接口

1) List集合类中元素有序(即添加顺序和取出顺序一致)、 且可重复[案例]

2) List集合中的每个元素都有其对应的顺序索引,即支持索引。[案例]

3) List容器中的元素都对应一 个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。

        List list = new ArrayList(;

4) JDK API中List接口的实现类有

 2.List的常用方法

        

public class ListMethod {@SuppressWarnings({"all"})public static void main(String[] args) {List list = new ArrayList();list.add("张三丰");list.add("贾宝玉");//void add(int index, Object ele):在index位置插入ele元素//在index = 1的位置插入一个对象list.add(1, "韩顺平");System.out.println("list=" + list);//boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来List list2 = new ArrayList();list2.add("jack");list2.add("tom");list.addAll(1, list2);System.out.println("list=" + list);//Object get(int index):获取指定index位置的元素//collection方法有//int indexOf(Object obj):返回obj在集合中首次出现的位置System.out.println(list.indexOf("tom"));//2//int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置list.add("韩顺平");System.out.println("list=" + list);System.out.println(list.lastIndexOf("韩顺平"));// Object remove(int index):移除指定index位置的元素,并返回此元素list.remove(0);System.out.println("list=" + list);//Object set(int index, Object ele):设置指定index位置的元素为ele , 相当于是替换.list.set(1, "玛丽");//一定要存在才能替换System.out.println("list=" + list);//List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合// 注意返回的子集合 fromIndex <= subList < toIndex [0,2)List returnlist = list.subList(0, 2);System.out.println("returnlist=" + returnlist);}
}

3.List练习

        

public class ListExercise {public static void main(String[] args) {List list = new ArrayList();for (int i = 0; i < 12; i++) {list.add("hello" + i);}//在索引为1插入一个元素list.add(1,"hspedu");System.out.println("list=" + list);//在abstractCollection内有toString方法//获得下标为4的元素System.out.println("第五个元素" + list.get(4));//删除下标为5的元素list.remove(5);System.out.println("list" + list);//修改第七个元素list.set(6,"三国演义");//使用迭代器for (Object o : list) {System.out.println(o);}Iterator iterator = list.iterator();while (iterator.hasNext()) {Object next =  iterator.next();System.out.println(next);}}
}

4.ListFor三种遍历方式与三种子类

        List的三种遍历方式while for增强 for普通

[ArrayList, LinkedList,Vector]三种运行类型。只要是实现List接口的子类都能这么遍历。(区别后面会讲)

//List 接口的实现子类 Vector LinkedList
List list = new ArrayList();
List list = new Vector();
List list = new LinkedList();

public class ListFor {@SuppressWarnings({"all"})public static void main(String[] args) {//List 接口的实现子类 Vector LinkedList//List list = new ArrayList();//换成ArrayList代码也不会报错//List list = new Vector();//换成Vector也不会报错List list = new LinkedList();list.add("jack");list.add("tom");list.add("鱼香肉丝");list.add("北京烤鸭子");//遍历//1. 迭代器Iterator iterator = list.iterator();while (iterator.hasNext()) {Object obj =  iterator.next();System.out.println(obj);}System.out.println("=====增强for=====");//2. 增强forfor (Object o : list) {System.out.println("o=" + o);}System.out.println("=====普通for====");//3. 使用普通forfor (int i = 0; i < list.size(); i++) {System.out.println("对象=" + list.get(i));}}
}

5.List接口课堂练习

                ​​​​​​​

public class ListExercise01 {@SuppressWarnings({"ALL"})public static void main(String[] args) {List list = new ArrayList();list.add(new Book("三国演义", "罗贯中", 10.1));list.add(new Book("小李飞刀", "古龙", 5.1));list.add(new Book("红楼梦", "曹雪芹", 34.6));list.add(new Book("活着", "余华", 12.4));list.add(new Book("3年模拟", "新华", 60.0));//如何对集合进行排序sort(list);for (Object o : list) {//直接sout(list)的话调用的是AbstactCoolection的toShtring方法,虽然也会调用对象的toString,但格式不对System.out.println(o);}}public static void sort(List list){for (int i = 0; i < list.size() - 1; i++) {for (int j = 0; j < list.size() - i - 1; j++) {//取出对象Book book = (Book)list.get(j);Book book1 = (Book)list.get(j + 1);if (book.getPrice() < book1.getPrice()){list.set(j,book1);list.set(j + 1,book);}}}}
}
class Book {private String name;private String author;private double price;public Book(String name, String author, double price) {this.name = name;this.author = author;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "名字=" + name + "\t\t作者=" + author + "\t\t价格=" + price;}
}

四、ArrayList 的底层结构和源码分析(建议多看看)

1.ArrayList的细节

        1)permits all elements, including null,ArrayList可以加入null,并且多个

        2) ArrayList是由数组来实现数据存储的

        3) ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码.,
在多线程情况下,不建议使用ArrayList

public class ArrayListDetail {public static void main(String[] args) {//ArrayList 是线程不安全的, 可以看源码 没有 synchronized/*public boolean add(E e) {ensureCapacityInternal(size + 1);  // Increments modCount!!elementData[size++] = e;return true;}*/ArrayList arrayList = new ArrayList();arrayList.add(null);arrayList.add("jack");arrayList.add(null);arrayList.add("hsp");System.out.println(arrayList);}
}

2.ArrayList的源码分析(重点难点)

1) ArrayList中维护了一个Object类型的数组elementData.

        transient Object[] elementData;//tansient表示瞬间,将来这个被修饰的对象不会被序列化

2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10, 如需要再次扩容,则扩容elementData为1.5倍。//每次都会检测扩容

3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。

用下列源码debug看

public class ArrayListSource {public static void main(String[] args) {//注意,注意,注意,Idea 默认情况下,Debug 显示的数据是简化后的,如果希望看到完整的数据//需要做设置.//使用无参构造器创建ArrayList对象ArrayList list = new ArrayList();// ArrayList list = new ArrayList(8);//使用for给list集合添加 1-10数据for (int i = 1; i <= 10; i++) {list.add(i);}//使用for给list集合添加 11-15数据for (int i = 11; i <= 15; i++) {list.add(i);}list.add(100);list.add(200);list.add(null);}
}

源码流程图

在debug的时候会出现数据省略的可以设置

省略null数据可以设置显示

五、Vector类的底层结构和源码分析(建议多看看)

1.Vector的基本介绍

        1) Vector类的定义说明

                public class Vector<E>

                extends AbstractList<E>

                implements List<E>, RandomAccess, Cloneable, Serializable

        2) Vector底层也是一个对象数组, protected Object[] elementData;

        3) Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized

                public synchronized E get(int index) {

                if (index > = elementCount)

                throw new ArrayIndexOutOfBoundsException(index);

                return elementData(index);

        4)在开发中,需要线程同步安全时,考虑使用Vector

public class Vector_ {public static void main(String[] args) {//无参构造器//有参数的构造Vector vector = new Vector(8);for (int i = 0; i < 10; i++) {vector.add(i);}vector.add(100);System.out.println("vector=" + vector);//1. new Vector() 底层/*public Vector() {this(10);}补充:如果是  Vector vector = new Vector(8);走的方法:public Vector(int initialCapacity) {this(initialCapacity, 0);}2. vector.add(i)2.1  //下面这个方法就添加数据到vector集合public synchronized boolean add(E e) {modCount++;ensureCapacityHelper(elementCount + 1);elementData[elementCount++] = e;return true;}2.2  //确定是否需要扩容 条件 : minCapacity - elementData.length>0private void ensureCapacityHelper(int minCapacity) {// overflow-conscious codeif (minCapacity - elementData.length > 0)grow(minCapacity);}2.3 //如果 需要的数组大小 不够用,就扩容 , 扩容的算法//newCapacity = oldCapacity + ((capacityIncrement > 0) ?//                             capacityIncrement : oldCapacity);//就是扩容两倍.private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + ((capacityIncrement > 0) ?capacityIncrement : oldCapacity);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);elementData = Arrays.copyOf(elementData, newCapacity);}*/}
}

2.Vector和ArrayList的比较


        

六、LinkedList的底层结构和源码分析

1.LinkedList的说明

        1) LinkedList实现了双向链表和双端队列特点

        2)可以添加任意元素(元素可以重复),包括null

        3)线程不安全,没有实现同步

2.模拟双向链表

1) LinkedList底层维护了一个双向链表

        ​​​​​​​        

2) LinkedList中维护了两个属性first和last分别指向首节点和尾节点

3)每个节点(Node对象),里面又维护了prev、next. item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表

4)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。

        ​​​​​​​        ​​​​​​​

        ​​​​​​​        

5)模拟一个简单的双向链表
 

public class LinkedList01 {public static void main(String[] args) {//模拟一个简单的双向链表Node jack = new Node("jack");Node tom = new Node("tom");Node hsp = new Node("老韩");//连接三个结点,形成双向链表(结点也叫对象//jack -> tom -> hspjack.next = tom;tom.next = hsp;//hsp -> tom -> jackhsp.pre = tom;tom.pre = jack;Node first = jack;//让first引用指向jack,就是双向链表的头结点Node last = hsp; //让last引用指向hsp,就是双向链表的尾结点//演示,从头到尾进行遍历System.out.println("===从头到尾进行遍历===");while (true) {if(first == null) {break;}//输出first 信息System.out.println(first);first = first.next;}//演示,从尾到头的遍历System.out.println("====从尾到头的遍历====");while (true) {if(last == null) {break;}//输出last 信息System.out.println(last);last = last.pre;}//演示链表的添加对象/数据,是多么的方便//要求,是在 tom --------- 老韩直接,插入一个对象 smith//1. 先创建一个 Node 结点,name 就是 smithNode smith = new Node("smith");//下面就把 smith 加入到双向链表了smith.next = hsp;smith.pre = tom;hsp.pre = smith;tom.next = smith;//让first 再次指向jackfirst = jack;//让first引用指向jack,就是双向链表的头结点System.out.println("===从头到尾进行遍历===");while (true) {if(first == null) {break;}//输出first 信息System.out.println(first);first = first.next;}last = hsp; //让last 重新指向最后一个结点//演示,从尾到头的遍历System.out.println("====从尾到头的遍历====");while (true) {if(last == null) {break;}//输出last 信息System.out.println(last);last = last.pre;}}
}//定义一个Node 类,Node对象,表示双向链表的一个结点
class Node {public Object item; //真正存放数据public Node next; //指向后一个结点(下一个public Node pre; //指向前一个结点(上一个public Node(Object name) {this.item = name;}public String toString() {return "Node name=" + item;}
}

        ​​​​​​​        

        ​​​​​​​        ​​​​​​​

 

3.LinkedListCURD分析

增加

 删除

public boolean add(E e) {linkLast(e);return true;}4.将新的结点,加入到双向链表的最后void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;size++;modCount++;}*///演示一个删除结点的linkedList.remove(); // 这里默认删除的是第一个结点//linkedList.remove(2);System.out.println("linkedList=" + linkedList);/*老韩读源码 linkedList.remove(); // 这里默认删除的是第一个结点1. 执行 removeFirstpublic E remove() {return removeFirst();}2. 执行public E removeFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return unlinkFirst(f);}/*3. 执行 unlinkFirst, 将 f 指向的双向链表的第一个结点拿掉private E unlinkFirst(Node<E> f) {// assert f == first && f != null;final E element = f.item;final Node<E> next = f.next;f.item = null;f.next = null; // help GCfirst = next;if (next == null)last = null;elsenext.prev = null;size--;modCount++;return element;}*///修改某个结点对象linkedList.set(1, 999);System.out.println("linkedList=" + linkedList);//得到某个结点对象//get(1) 是得到双向链表的第二个对象Object o = linkedList.get(1);System.out.println(o);//999//因为LinkedList 是 实现了List接口, 遍历方式System.out.println("===LinkeList遍历迭代器====");Iterator iterator = linkedList.iterator();while (iterator.hasNext()) {Object next =  iterator.next();System.out.println("next=" + next);}System.out.println("===LinkeList遍历增强for====");for (Object o1 : linkedList) {System.out.println("o1=" + o1);}System.out.println("===LinkeList遍历普通for====");for (int i = 0; i < linkedList.size(); i++) {System.out.println(linkedList.get(i));}}
}

 4.ArrayList和inkedList的比较

如何选择ArrayList和LinkedList:

        两个都是线程不安全的

1)如果我们改查的操作多,选择ArrayList

2)如果我们增删的操作多,选择LinkedList

3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList

4)在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList.
 

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

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

相关文章

Elasticsearch下载安装,IK分词器、Kibana下载安装使用,elasticsearch使用演示

首先给出自己使用版本的网盘链接&#xff1a;自己的版本7.17.14 链接&#xff1a;https://pan.baidu.com/s/1FSlI9jNf1KRP-OmZlCkEZw 提取码&#xff1a;1234 一般情况下 Elastic Search&#xff08;ES&#xff09; 并不单独使用&#xff0c;例如主流的技术组合 ELK&#xff08…

MyBatis Plus之wrapper用法

一、条件构造器关系 条件构造器关系介绍&#xff1a; 绿色框&#xff1a;抽象类 abstract 蓝色框&#xff1a;正常 class 类&#xff0c;可 new 对象 黄色箭头&#xff1a;父子类关系&#xff0c;箭头指向为父类 wrapper介绍&#xff1a; Wrapper &#xff1a;条件构造抽象类…

mac m1下navicat执行mongorestore 到mongodb

首先&#xff0c;下载https://www.mongodb.com/try/download/mongocli 解压缩后 有可执行文件使用navicat打开 加载后再重新点击 选择 要恢复的文件即可

CDN加速技术海外与大陆优劣势对比

内容分发网络&#xff08;CDN&#xff09;是一项广泛应用于网络领域的技术&#xff0c;旨在提高网站和应用程序的性能、可用性和安全性。CDN是一种通过将内容分发到全球各地的服务器来加速数据传输的服务。本文将探讨使用CDN的优势以及国内CDN和海外CDN之间的不同优势和劣势。 …

【C语言】函数指针存疑调试及回调函数编写(结构体内的Callback回调函数传参和虚伪的回调函数__weak声明)

【C语言】函数指针存疑调试及回调函数编写&#xff08;结构体内的Callback回调函数传参和虚伪的回调函数__weak声明&#xff09; 文章目录 函数指针存疑调试函数指针函数调用 回调函数编写结构体内的回调函数虚伪的回调函数 附录&#xff1a;压缩字符串、大小端格式转换压缩字符…

数据结构——双向链表的实现

一、双向链表的结构 注意&#xff1a;双向链表又称带头双向循环链表 这⾥的“带头”跟前⾯我们说的“头节点”是两个概念&#xff0c;实际前⾯的在单链表阶段称呼不严 谨&#xff0c;但是为了同学们更好的理解就直接称为单链表的头节点。 带头链表⾥的头节点&#xff0c;实际…

MySQL---数据用户管理和索引

DDL&#xff1a;CTEATE DROP ALTER dml&#xff1a;对数据进行管理 update insert into delete truncate dpl&#xff1a;查询语句 select dcl&#xff1a;权限控制语句 grant revoke 数据库用户管理 创建用户 修改用户权限 删除用户 grant要在终端执行 创建用户 cr…

function函数指针和lamada的[]和[=]注意事项

在工作的过程中&#xff0c;lamda表达式的 重点&#xff1a; 1.function对象存储函数指针。 2.lamada表达式&和捕捉的方式 lamda传入引用&&#xff0c;导致作用域消失&#xff0c;最终报错 std::function<void()> pFun; void GetNum1(const std::function<…

企业在招标流程中面临的 6 大挑战

采购中的招标是一种采购策略&#xff0c;包括向不同的销售商/供应商询价&#xff08;RFQ&#xff09;和索取资料&#xff08;RFI&#xff09;&#xff0c;以比较其特点、价格和功能。 工作团队在招标采购流程中投入了数个小时&#xff0c;但在整个过程中仍不得不忍受失望和不适…

【抓包分析】通过ChatGPT解密还原某软件登录算法实现绕过手机验证码登录

文章目录 &#x1f34b;前言实现效果成品广告抓包分析一、定位加密文件二、编辑JS启用本地替换 利用Chatgpt进行代码转换获取计划任务id模拟数据请求最后 &#x1f34b;前言 由于C站版权太多&#xff0c;所有的爬虫相关均为记录&#xff0c;不做深入&#xff01; 今天发现gith…

数据结构 | 算法的时间复杂度和空间复杂度【详解】

数据结构 | 算法的时间复杂度和空间复杂度【详解】 文章目录 数据结构 | 算法的时间复杂度和空间复杂度【详解】1. 什么是数据结构&#xff1f;2. 什么是算法&#xff1f;3. 算法效率4. 时间复杂度4.1 时间复杂度的概念4.2 推导大O阶的方法&#xff1a;4.3 常见时间复杂度计算举…

Leetcode—274.H指数【中等】

2023每日刷题&#xff08;十三&#xff09; Leetcode—274.H指数 算法思想 参考自灵茶山艾府 实现代码 int minValue(int a, int b) {return a < b ? a : b; }int hIndex(int* citations, int citationsSize){int cnt[5001] {0};int i;for(i 0; i < citationsSize; …

SpringBoot 公司推广系统 公司广告系统

SpringBoot 公司推广系统 公司广告系统 系统功能 首页功能: 广告展示 方案列表 站内搜索 资讯 查看详细咨询 登录注册 收藏 咨询方案 在线客服实时聊天 后台管理功能: 系统管理分为: 用户管理 角色管理 客户管理 首页轮播管理 公告管理 方案管理: 方案管理 资讯管理: 类型管…

【C++项目】高并发内存池第五讲内存回收释放过程介绍

内存回收 1.ThreadCache2.CentralCache3.PageCache 项目源代码&#xff1a;高并发内存池 1.ThreadCache void ThreadCache::Deallocate(void* ptr, size_t size) {assert(ptr);assert(size < MAX_BYTES);//计算在哪号桶中&#xff0c;然后插入进去size_t index SizeClass…

c++ pcl 选取点云某一点反馈XYZ坐标的代码

看了看以前的代码&#xff0c;有一小段代码很有意思&#xff0c;是关于pcl点云处理的。 如有帮助&#xff0c;点赞收藏关注&#xff01;&#xff01;&#xff01; 读取点云数据&#xff0c;想可视化点云数据&#xff0c;并根据选择&#xff0c;实时显示点云的空间坐标数值。 接…

关于FreeTypeFont‘ object has no attribute ‘getsize‘问题的解决方案

引言 这个问题是在训练yolov5_obb项目遇到的&#xff0c;大概率又是环境问题。如下图&#xff1a; 解决方法 出现这个问题是Pillow版本太高了&#xff0c;下载低版本的&#xff1a; pip install Pillow9.5 OK&#xff01;

Java List Set Map

一、List 1.1 ArrayList 1.2 LinkedList 二、Set 2.1 HashSet 2.2 TreeSet 2.3 LinkedHashSet 三、Map 3.1 HashMap 3.2 TreeMap 3.3 LinkedHashMap 四、对比 类型底层结构重复null值场景备注查询删除新增ListArrayList动态数组可允许快速随机访问元素0(1)0(n)尾部增加0&a…

[已解决]虚拟机之前能正常上网,重启之后无法连接网络问题的解决方法

虚拟机之前网络正常&#xff0c;重启之后却始终连接不上网络。 找了许多方法&#xff0c;终于发现一种便捷有效的方法。 解决方法如下&#xff1a; 1、将网络模式更改为NAT模式., 2、打开终端窗口&#xff0c;输入如下命令。 sudo service network-manager stopsudo rm /var/l…

LeetCode | 17.04.消失的数字和189.旋转数组

LeetCode | 17.04.消失的数字和189.旋转数组 文章目录 LeetCode | 17.04.消失的数字和189.旋转数组17.04.消失的数字方法一&#xff1a;方法二&#xff1a;方法三&#xff1a;方法二的代码方法三的代码 189.旋转数组思路一思路二思路三 17.04.消失的数字 OJ链接 这里题目要求…

10、电路综合-基于简化实频的宽带匹配电路设计方法

10、电路综合-基于简化实频的宽带匹配电路设计方法 网络综合和简化实频理论学习概述中的1-9介绍了SRFT的一些基本概念和实验方法&#xff0c;终于走到了SRFT的另一个究极用途&#xff0c;宽带匹配电路的设计。 1、之前的一些回顾与总结 之前也给出了一些电路综合的案例&…