JAVA小知识20:万字详解List与ArrayList

一、集合简介

1.1、什么是集合?

可同时存储多个元素的数据结构就是集合。

1.2、为什么要有集合?

我们可以使用数组同时存储多个元素,但是数组有个弊端。数组创建之后长度就会固定,如需扩容则需要手动扩容,我们需要一个长度可变的新的容器(自动扩容)。

1.3、集合与数组的区别

数组可以存储基本数据类型,也可以存储引用数据类型。但是集合是不能直接存储基本数据类型的,需要把它转化为对应的包装类。

1.4、集合都有什么?

Java 集合框架可以分为两条大的支线:Collection接口与Map接口

  • Collection接口:
    • List接口:有序集合,允许重复元素。
      • ArrayList:基于动态数组实现,支持快速随机访问。
      • LinkedList:基于双向链表实现,适合频繁插入和删除操作。
  • Set接口:无序集合,不允许重复元素。
    • HashSet:基于哈希表实现,元素无序。
    • LinkedHashSet:继承自HashSet,维护插入顺序。
    • TreeSet:基于红黑树实现,元素有序。
  • Queue接口:用于处理先进先出(FIFO)的队列。
    • PriorityQueue:基于堆实现的优先级队列,元素按自然顺序或指定的Comparator排序。
  • Deque接口:双端队列,支持在两端插入和删除元素。
    • ArrayDeque:基于数组实现的双端队列。
    • LinkedList:也实现了Deque接口。
  • Map接口:
    • HashMap:基于哈希表实现,键值对无序。
    • LinkedHashMap:继承自HashMap,维护插入顺序。
    • TreeMap:基于红黑树实现,键值对有序。

我们引用一张图片就能很好地来解释上面的文字:
在这里插入图片描述
今天我们要研究的目标是List这条分支,也是我们开发中最常用的一种集合。

二、List

2.1、List简介

List接口是Java集合框架中的一部分,提供了一组有序的、可重复的元素集合。List接口继承自Collection接口,并在其基础上添加了允许精确控制元素插入位置的操作。

java.util.Collection 接口是 Java 集合框架的根接口之一,它定义了一组通用的方法,用于操作集合中的元素。Collection 接口是 Java 集合框架中所有集合类的共同父接口。

2.2、主要特点

  • 有序性:List接口保证元素的插入顺序,即元素的迭代顺序与插入顺序一致。
  • 可重复性:List接口允许存储重复的元素。
  • 索引访问:List接口提供了基于索引的位置访问元素的能力,类似于数组。

2.3、主要实现类

List接口有几个常用的实现类,每个类有其特定的特点和使用场景:

  • ArrayList:
    • 基于动态数组实现,支持快速随机访问。
    • 适合频繁读取元素的场景。
    • 插入和删除操作相对较慢,尤其是在列表中间插入或删除时。
  • LinkedList:
    • 基于双向链表实现,适合频繁插入和删除操作。
    • 读取速度较慢,因为需要从头遍历到指定位置。
    • 也实现了Deque接口,可以用作双端队列。

2.4、实现类对比

  • ArrayList:适用于随机访问频繁的场景,因为基于数组的实现提供了快速的索引访问。
  • LinkedList:适用于插入和删除操作频繁的场景,因为基于链表的实现提供了更高效的插入和删除操作。

2.5、为什么要用实现类?

在 Java 中,List 是一个接口(java.util.List),而不是一个具体的类。接口本身不能直接实例化为对象,因为它只是一组方法的声明,没有实际的方法实现。所以我们要想实现List,就要做一个向上造型,其中 ArrayList 是 List 接口的子类。将 ArrayList 类的对象赋值给 List 接口的引用,这是一种向上造型操作。这允许各位程序员使用 List 接口的方法来操作 ArrayList 对象,因为 ArrayList 实现了 List 接口,所以它是 List 接口的一个实例。

三、ArrayList

ArrayList 在数组的基础上实现了自动扩容,并且提供了比数组更丰富的预定义方法(各种增删改查),非常方便我们在开发中的使用。

3.1、创建ArrayList

先来看看List的源码:
在这里插入图片描述
我们可以看到List确确实实是继承了Collection,并且他也是一个接口,而且他还有个泛型(关于泛型的知识在java小知识19里面可以看看)。下面我们来看构造方法:
在这里插入图片描述
那我们如何初始化一个ArrayList集合呢?下面有两种方法,我们常用的为方法一。我们可以看到泛型(泛型只能是引用数据类型)里面规定了这个集合只能存储Integer包装类的数据。
在这里插入图片描述

3.2、ArrayList的成员方法

讲完了如何创建一个ArrayList我们来讲讲如何使用ArrayList

方法名描述
add()将元素插入到指定位置的 ArrayList
addAll()添加集合中的所有元素到 ArrayList
clear()删除 ArrayList 中的所有元素
clone()复制一份 ArrayList
contains()判断元素是否在 ArrayList
get()通过索引值获取 ArrayList 中的元素
indexOf()返回 ArrayList 中元素的索引值
removeAll()删除存在于指定集合中的 ArrayList 里的所有元素
remove()删除 ArrayList 里的单个元素
size()返回 ArrayList 里元素数量
isEmpty()判断 ArrayList 是否为空
subList()截取部分 ArrayList 的元素
set()替换 ArrayList 中指定索引的元素
sort()ArrayList 元素进行排序
toArray()ArrayList 转换为数组
toString()ArrayList 转换为字符串
ensureCapacity()设置指定容量大小的 ArrayList
lastIndexOf()返回指定元素在 ArrayList 中最后一次出现的位置
retainAll()保留 ArrayList 中在指定集合中也存在的那些元素
containsAll()查看 ArrayList 是否包含指定集合中的所有元素
trimToSize()ArrayList 中的容量调整为数组中的元素个数
removeRange()删除 ArrayList 中指定索引之间存在的元素
replaceAll()将给定的操作内容替换掉数组中每一个元素
removeIf()删除所有满足特定条件的 ArrayList 元素
forEach()遍历 ArrayList 中每一个元素并执行特定操作

3.3、ArrayList的特性

  1. 动态数组: ArrayList是基于动态数组实现的,它允许存储和操作一个可变数量的元素。数组的容量会自动增长或减少,以适应元素的添加和删除操作,因此无需手动管理数组的大小。
  2. 有序性: ArrayList 是有序集合,它以元素插入的顺序来维护元素的顺序。这意味着可以按照添加元素的顺序来访问和遍历元素。
  3. 允许重复元素: ArrayList 允许存储重复的元素,即同一个元素可以在列表中出现多次。
  4. 随机访问: 由于 ArrayList 基于数组实现,因此它支持随机访问。可以通过索引来直接访问列表中的元素。
  5. 线程不安全: ArrayList 不是线程安全的,这意味着在多线程环境下,如果多个线程同时访问和修改同一个 ArrayList 实例,可能会导致数据不一致或异常。如果需要在多线程环境中使用,可以考虑使用 Collections.synchronizedList() 方法来获得一个线程安全的 ArrayList。
  6. 性能: 由于 ArrayList 支持随机访问,因此对于需要频繁访问元素的场景非常高效。然而,在需要频繁插入或删除元素的情况下,性能可能较差,因为这涉及到数组元素的移动。
  7. 动态扩容: 当 ArrayList 内部数组的容量不足以容纳新元素时,它会自动扩展数组的大小,通常是当前容量的一半。这可以避免频繁的数组重新分配操作,提高了性能。

四、ArrayList成员方法详解

4.1、add():将元素插入到指定位置的 ArrayList 中。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add(1, "Banana"); // 在索引1处插入
System.out.println(list); // 输出: [Apple, Banana]

4.2、addAll():添加集合中的所有元素到 ArrayList 中。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
List<String> moreFruits = Arrays.asList("Banana", "Orange");
list.addAll(moreFruits);
System.out.println(list); // 输出: [Apple, Banana, Orange]

4.3、clear():删除 ArrayList 中的所有元素。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.clear();
System.out.println(list); // 输出: []

4.4、clone():复制一份 ArrayList。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
ArrayList<String> clonedList = (ArrayList<String>) list.clone();
System.out.println(clonedList); // 输出: [Apple]

4.5、contains():判断元素是否在 ArrayList 中。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
boolean hasApple = list.contains("Apple");
System.out.println(hasApple); // 输出: true

4.6、get():通过索引值获取 ArrayList 中的元素。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
String fruit = list.get(0);
System.out.println(fruit); // 输出: Apple

4.7、indexOf():返回 ArrayList 中元素的索引值。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
int index = list.indexOf("Banana");
System.out.println(index); // 输出: 1

4.3、removeAll():删除存在于指定集合中的 ArrayList 里的所有元素。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");
List<String> toRemove = Arrays.asList("Banana", "Orange");
list.removeAll(toRemove);
System.out.println(list); // 输出: [Apple]

4.3、remove():删除 ArrayList 里的单个元素。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.remove("Apple");
System.out.println(list); // 输出: []

4.3、size():返回 ArrayList 里元素数量。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
int size = list.size();
System.out.println(size); // 输出: 1

4.3、isEmpty():判断 ArrayList 是否为空。

ArrayList<String> list = new ArrayList<>();
boolean empty = list.isEmpty();
System.out.println(empty); // 输出: true

4.3、subList():截取部分 ArrayList 的元素。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");
List<String> subList = list.subList(1, 3);
System.out.println(subList); // 输出: [Banana, Orange]

4.3、set():替换 ArrayList 中指定索引的元素。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.set(0, "Banana");
System.out.println(list); // 输出: [Banana]

4.3、sort():对 ArrayList 元素进行排序。

ArrayList<String> list = new ArrayList<>();
list.add("Banana");
list.add("Apple");
list.sort(String::compareTo);
System.out.println(list); // 输出: [Apple, Banana]

4.3、toArray():将 ArrayList 转换为数组。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
Object[] array = list.toArray();
System.out.println(Arrays.toString(array)); // 输出: [Apple]

4.3、toString():将 ArrayList 转换为字符串。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
String str = list.toString();
System.out.println(str); // 输出: [Apple]

4.3、ensureCapacity():设置指定容量大小的 ArrayList。

ArrayList<String> list = new ArrayList<>();
list.ensureCapacity(100);
list.add("Apple");
System.out.println(list); // 输出: [Apple]

4.3、lastIndexOf():返回指定元素在 ArrayList 中最后一次出现的位置。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Apple");
int lastIndex = list.lastIndexOf("Apple");
System.out.println(lastIndex); // 输出: 2

4.3、retainAll():保留 ArrayList 中在指定集合中也存在的那些元素。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
List<String> toRetain = Arrays.asList("Apple");
list.retainAll(toRetain);
System.out.println(list); // 输出: [Apple]

4.3、containsAll():查看 ArrayList 是否包含指定集合中的所有元素。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
List<String> toCheck = Arrays.asList("Apple", "Banana");
boolean containsAll = list.containsAll(toCheck);
System.out.println(containsAll); // 输出: true

4.3、trimToSize():将 ArrayList 中的容量调整为数组中的元素个数。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.trimToSize();
System.out.println(list); // 输出: [Apple]

4.3、removeRange():删除 ArrayList 中指定索引之间存在的元素。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");
list.subList(1, 2).clear(); // 删除索引1到2之间的元素
System.out.println(list); // 输出: [Apple, Orange]

4.3、replaceAll():将给定的操作内容替换掉数组中每一个元素。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.replaceAll(fruit -> fruit.toUpperCase());
System.out.println(list); // 输出: [APPLE, BANANA]

4.3、removeIf():删除所有满足特定条件的 ArrayList 元素。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.removeIf(fruit -> fruit.startsWith("A"));
System.out.println(list); // 输出: [Banana]

4.3、forEach():遍历 ArrayList 中每一个元素并执行特定操作。

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.forEach(fruit -> System.out.println(fruit));

五、ArrayList的扩容机制

结合源码我们来讲一下ArrayList的扩容机制

第一步:创建ArrayList对象

首先我们来看一下创建一个ArrayList对象的时候都发生了什么

public static void main(String[] args) {List<String> list = new ArrayList<>();
}

ArrayList在底层有一个数组,他的名字叫做elementData,他还有一个成员变量size记录元素的个数。
在这里插入图片描述

如果利用空参的构造方法或者参数为0的情况下,在底层他会默认创建一个长度为0的数组
在这里插入图片描述
在这里插入图片描述
也就是说我们创建一个空参ArrayList对象时候,他的数组长度为0

第二步、添加元素

我们来看看当向ArrayList集合中添加第一个元素时候发生了什么。

当第一次添加元素时,ArrayList 会检查是否需要扩容。在 add 方法中,会调用ensureCapacityInternal 方法来确保容量足够:
在这里插入图片描述

然后我们来看那可能这个ensureCapacityInternal(size + 1); 方法是怎么来保证容量是足够的。

当我们刚刚创建这个ArrayList的时候,他的size值为0,而+1之后参数就为1。
此时,就变成了ensureCapacityInternal(1)
ensureCapacityInternal()方法会调用 ensureExplicitCapacity 来判断是否需要扩容:
在这里插入图片描述

此时又来了一个方法,我们先看看这个calculateCapacity(elementData, minCapacity)都干了什么?

两个参数,一个是底层数组,一个是刚刚传过来的size+1,底层数组在初始化的时候赋值的就是空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA,所以满足if条件在这里插入图片描述
而这个DEFAULT_CAPACITY这个常量在源码中的默认值就是10。minCapacity的值为1。所以会返回10

说完了calculateCapacity(elementData, minCapacity)我们接着来看最外层的ensureExplicitCapacity()都干了什么?

在这里插入图片描述

第三步、扩展数组

重点来了!!!可以看到初始数组长度为0,进入到了grow()函数,这个函数就是扩容函数,我们来详细的分析看看。

先上完整代码:
在这里插入图片描述

1、变量初始化

// overflow-conscious code
int oldCapacity = elementData.length;

elementData.length 表示当前 ArrayList 内部数组的长度,即当前容量。
oldCapacity 就是当前数组的长度,即当前 ArrayList的容量。
2、计算新容量

int newCapacity = oldCapacity + (oldCapacity >> 1);

oldCapacity >> 1 是对 oldCapacity 进行右移一位的操作,相当于 oldCapacity / 2。这一步是为了将当前容量增加 50%
newCapacity 就是计算出来的新容量,通常是当前容量的1.5倍。
3、调整新容量

if (newCapacity - minCapacity < 0)newCapacity = minCapacity;

这里判断如果 newCapacity(计算后的新容量) 小于 minCapacity(参数),则将newCapacity设置为 minCapacity。这是为了确保扩容后的容量至少能够满足 minCapacity,即确保能够容纳至少 minCapacity 个元素。
4、最大容量限制

if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);

MAX_ARRAY_SIZE 是 ArrayList 内部定义的一个常量,表示数组的最大容量。如果 newCapacity 超过了 MAX_ARRAY_SIZE,则调用hugeCapacity方法进行处理,通常是返回一个较大的合理容量。
5、扩容操作

// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);

·Arrays.copyOf ·方法用于将 ·elementData· 数组扩展到 ·newCapacity ·的大小,并复制原数组的内容到新数组中。这一步实现了真正的扩容操作

关于这个copyof可以看一下我的java小知识18有讲过,这里也直接贴出截图:
在这里插入图片描述

六、关于ArrayList的一些问答

6.1 ArrayList的扩容机制

上面五讲过了

6.2 ArrayList频繁扩容导致性能下降问题

问题:
假设现在需要添加10w条数据,可能时间上很快,不到1s就能添加完,但是这其中ArrayList就会扩容n次,并且重复拷贝n次,这样的操作非常的占用我们的内存开销。
答案:
可以使用有参构造来创建ArrayList,然后添加元素。看下列示例,同样添加10w条数据。

public static void main(String[] args) {long t1 = System.currentTimeMillis();List<String> list = new ArrayList<>();for(int i=0; i<100000; i++) {list.add(i+"a");}long t2 = System.currentTimeMillis();System.out.println("方法一运行:"+(t2 - t1)+"毫秒");long t3 = System.currentTimeMillis();List<String> list2 = new ArrayList<>(100000);for(int i=0; i<100000; i++) {list2.add(i+"a");}long t4 = System.currentTimeMillis();System.out.println("方法二运行:"+(t4 - t3)+"毫秒");
}

在这里插入图片描述

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

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

相关文章

图像的对比度和亮度

目标 访问像素值用0来初始化矩阵cv::saturate_cast像素转换提高一张图像的亮度 原理 图像处理 图像变换可以被视作两个步骤&#xff1a; 点操纵&#xff08;像素转换&#xff09;相邻区域转换&#xff08;以面积为基础&#xff09; 像素转换 在这种图像处理的转换过程中…

oracle发送邮件附件的步骤?怎么配置发信?

oracle发送邮件附件的操作指南&#xff1f;Oracle邮件服务如何&#xff1f; 在Oracle数据库中&#xff0c;发送电子邮件附件是一项常见的任务&#xff0c;特别是在需要自动化通知或报表分发的情况下。AokSend将介绍如何使用Oracle数据库发送带有附件的电子邮件。以下是详细的步…

RTSP/Onvif安防监控平台EasyNVR抓包命令tcpdump使用不了,该如何解决?

安防视频监控汇聚EasyNVR智能安防视频监控平台&#xff0c;是基于RTSP/Onvif协议的安防视频平台&#xff0c;可支持将接入的视频流进行全平台、全终端分发&#xff0c;分发的视频流包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等格式。平台可提供的视频能力包括&#xff1a;…

LVS负载均衡集群企业级应用实战-LVS-DR(四)

目录 LVS-DR 一. 环境准备 二. 对虚拟主机操作 三. 对真实服务器操作 四. 打开网页测试 LVS-DR 一. 环境准备 三台虚拟机&#xff0c;都要在同一网段内&#xff0c;统一关闭防火墙和selinux&#xff0c;时间同步&#xff0c;配置好YUM源。系统用centos和roucky都行。 主…

2024最新版Node.js下载安装及环境配置教程(非常详细)

一、进入官网地址下载安装包 官网&#xff1a;Node.js — Run JavaScript Everywhere 其他版本下载&#xff1a;Node.js — Download Node.js (nodejs.org) 选择对应你系统的Node.js版本 二、安装程序 &#xff08;1&#xff09;下载完成后&#xff0c;双击安装包&#xf…

软考【网络管理员】100道高频考题(含知识点解析),轻松45+

2024上软考已经圆满结束了&#xff0c;距离下半年的考试也只剩下半年不到的时间。需要备考下半年软考网络管理员的小伙伴们可以抓紧开始准备了。 今天给大家整理了——软考网管100道高频考题 &#xff0c;都是核心重点&#xff0c;有PDF&#xff0c;看完一遍教材后打印出来直接…

【电子实验4】TDA2030功率放大电路

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…

GPRS抄表技术是什么?

1.GPRS抄表技术概述 GPRS(GeneralPacketRadioService)抄表是一种基于移动通信网络的远程抄表技术&#xff0c;它利用GPRS网络进行数据传输&#xff0c;实现了对水、电、气等公用事业表计的实时、远程读取。这项技术的出现&#xff0c;极大地提升了公用事业管理的效率和准确性&…

编写一个简单的Mybatis插件

1.编写一个类&#xff0c;实现Intercepter这个接口 2.完成这个类的方法&#xff0c;并通过注解Intercepts来告诉Mybatis这个插件拦截哪个类和哪个方法 3.在Mybatis的全局配置文件里注册这个插件&#xff0c;让插件生效 4.玩一个实际功能的插件

【leetcode刷题】面试经典150题 88.合并两个有序数组

leetcode刷题 面试经典150 88. 合并两个有序数组 难度&#xff1a;简单 文章目录 一、题目内容二、自己实现代码2.1 实现思路2.2 实现代码2.3 结果分析 三、 官方解法3.1 直接合并后排序3.1.1 算法实现3.1.2 代码实现3.1.3 代码分析 3.2 双指针3.2.1 算法实现3.2.2 代码实现3.2…

【安装笔记-20240616-Windows-Gpg4win 证书管理器】

安装笔记-系列文章目录 安装笔记-20240616-Windows-Gpg4win 证书管理器 文章目录 安装笔记-系列文章目录安装笔记-20240616-Windows-Gpg4win 证书管理器 前言一、软件介绍名称&#xff1a;Gpg4win主页官方介绍 二、安装步骤测试版本&#xff1a;Gpg4win 4.3.1下载链接安装界面…

网站的文章起到什么作用

1.便于用户了解产品服务 如果想要获得更多的用户访问或者转化率&#xff0c;那么网站就得需要高质量、高原创的文章&#xff0c;通过文章可以让用户更好的了解公司的产品和服务&#xff0c;用户会根据自己的需求去选择服务类型&#xff0c;从而可以给公司产生业务订单&am…

攻防演练之-网络安全工作机会大巡礼

书接上文&#xff0c;《网络安全攻防演练风云》专栏之攻防演练之-成功的钓鱼邮件溯源&#xff0c;这里。 午餐的时间到了&#xff0c;每天Nick团队的小伙伴都会到园区外的一家工作餐饭店就餐。这家餐厅是按照称重模式进行菜品选取的&#xff0c;因此种类是相对丰富的&#xff…

android studio 模拟器文件查找

android studio 模拟器文件查找 使用安卓模拟器下载文件后通常无法在系统硬盘上找到下载的文件&#xff0c;安卓 studio studio 其实提供了文件浏览工具&#xff0c;找到后可以直接使用 Android studio 打开 打开 Android studioview 菜单view > Tool Windows > Device…

直播中的美颜技术详解:视频美颜SDK的开发与应用

今天&#xff0c;笔者将深入探讨直播中的美颜技术&#xff0c;解析视频美颜SDK的开发与应用。 一、视频美颜技术概述 视频美颜技术主要通过实时处理视频流&#xff0c;对人脸进行优化和修饰&#xff0c;使直播画面更加美观。这些功能不仅提升了用户的直播体验&#xff0c;还极…

【django问题集】django.db.utils.OperationalError: (1040, ‘Too many connections‘)

一、报错内容 django.db.utils.OperationalError: (1040, Too many connections) 主要体现&#xff1a;就是请求不了后台&#xff0c;登录都登录不了。 二、代码优化 原生django配置的mysql连接是没有连接池的功能&#xff0c;会导致mysql连接创建过多导致连接数超过了mysql服…

Paragon NTFS for Mac 15软件下载及安装教程

简介&#xff1a; NTFS For Mac 15是首个支持Mac上读写NTFS外置存储设备解决方案 &#xff0c;解决mac不能读写外置让您更加简单直观的在Mac机上随意对NTFS文件修改、删除等操作。 安 装 包 获 取 地 址&#xff1a; Paragon Ntfs For Mac 15版&#xff1a; ​​https://sou…

Android出海实战:Firebase Analytics埋点

大家好&#xff0c;我是小编阿文。欢迎您关注我们&#xff0c;经常分享有关Android出海&#xff0c;iOS出海&#xff0c;App市场政策实时更新&#xff0c;互金市场投放策略&#xff0c;最新互金新闻资讯等文章&#xff0c;期待与您共航世界之海。 写在伊始 Google Analytics&…

二刷算法训练营Day30 | 回溯算法(6/6)

目录 详细布置&#xff1a; 1. 回溯总结 2. 332. 重新安排行程 3. 51. N 皇后 4. 37. 解数独 详细布置&#xff1a; 1. 回溯总结 回溯是递归的副产品&#xff0c;只要有递归就会有回溯&#xff0c;所以回溯法也经常和二叉树遍历&#xff0c;深度优先搜索混在一起&#x…

时代巨兽!深度神经网络如何改变我们的世界?

深度神经网络 1、 简介1.1 定义深度神经网络1.2 深度学习的发展历程1.3 深度神经网络的应用领域 2、深度神经网络的基本原理2.1 神经元层2.1.1 神经元2.1.2 神经元层 2.2 前向传播2.3 反向传播2.4 激活函数2.4.1、作用2.4.2、常见激活函数2.4.3、选择激活函数的考虑 2.5 损失函…