当前位置: 首页 > news >正文

ArrayList源码分析(JDK17)

ArrayList类

  • 简介
  • 类层次结构
  • 构造
    • 无参构造
    • 有参构造
  • 添加元素
    • add:添加/插入一个元素
    • addAll:添加集合中的元素
  • 扩容
  • mount与迭代器
  • 其他常见方法
  • 不常见方法
  • 不常见方法的源码和小介绍
  • 常见方法的源码和小介绍
  • 积累面试题
    • ArrayList是什么?可以用来干嘛?
    • ArrayList 的默认长度
    • ArrayList如何扩容
    • ArrayList频繁扩容导致性能下降该怎么办
    • 什么情况下你会使用ArrayList?什么时候你会选择LinkedList?
    • ArrayList的插入或删除一定比LinkedList慢吗


写在前面:

第一次写源码分析,感觉写起来,不知道从何下手,不过慢慢的也就写完了,也不知道条理怎么样,内容应该还是都说了。希望能对ArrayList的理解有所帮助.
本文通过ArrayList对动态数组的实现/生命周期来进行源码的解析。会列举源码并注释代码的作用。但不会讲述动态数组的实现过程,实现过程在数组–java–动态数组已经写过了

明天在继续写

本文内容包括:

    • 源码分析
    • 扩容机制
    • 迭代器
    • 面试题
    • 简介

      此类是 Java 集合框架的成员。 ArrayList 是一个数组队列,相当于动态数组。与Java中的数组相比,它的容量能动态增长。使用量很大,所以作为第一个进行源码分析的类。

      类层次结构

      继承于AbstractList抽象类
      在这里插入图片描述
      实现了:

      1. List
        有序集合(也称为 序列)的接口
      2. RandomAccess
        标记性接口,使得随机访问比迭代器快
      3. Cloneable
        标记性接口,克隆
        所以重写clone方法完成浅克隆
      4. java.io.Serializable
        标记性接口,序列化

      构造

      ArrayList的构造方法一共有3个
      在这里插入图片描述

      无参构造

      在这里插入图片描述
      elementData代表着的就是存储元素的数组了。
      transient关键字代表着其不能被序列化
      在这里插入图片描述

      注释上写着构造一共初始容量为10的空列表。但是我们打开DEFAULTCAPACITY_EMPTY_ELEMENTDATA这个类查看。很明显,这就是一个空数组,所以最开始的数组大小就是0。
      这个也算是慢初始,因为可能构造了不用,所以设置为空就会减少空间的浪费。
      在这里插入图片描述
      但为什么要这么写呢?
      我们可以看到这样一个属性,我们在扩容的时候用到这个,会导致无参构造扩容后就会是10.而在调用add后动态的初始化。

      在这里插入图片描述

      有参构造

      根据你传入的参数来构建大小,如果为0则会赋值一个空数组(但是这个和无参的不一样)
      在这里插入图片描述

      这个构造先判断传入集合的大小,如果为空则设置为空数组。
      如果不为空则判断是否的ArrayList类,是则直接赋值了,不是则进行拷贝。
      在这里插入图片描述

      添加元素

      add:添加/插入一个元素

      这里和jdk8会不一样
      modCount继承于AbstractList,记录着集合的修改次数
      然后调用了add(E e, Object[] elementData, int s)方法(jdk8直接实现出来了,而不是抽取方法)
      返回一个true代表添加成功
      在这里插入图片描述
      这段代码是很平常的添加代码,有意思的是这个注释。
      查阅资料发现,当方法字节码大小小于35的时候,会进行方法内联
      而这个操作由c1编译器进行。c1编译器(适用于执行时间较短或对启动性能有要求的程序)会比c2要快,所以可以让这个add成为热点,而被优化。
      这个部分应该属于JIT优化。
      在这里插入图片描述

      public void add(int index, E element)

      /**
      在此列表中的指定位置插入指定的元素。将当前位于该位置的元素(如果有)和任何后续元素向右移动(将一个元素添加到其索引中)。
      形参:
      index – 要插入指定元素的索引 element – 要插入的元素
      抛出:
      IndexOutOfBoundsException – 如果索引超出范围 (index < 0 || index > size())
      **/public void add(int index, E element) {rangeCheckForAdd(index); // 进行index范围的检查,超出范围会抛出异常modCount++;final int s;Object[] elementData;if ((s = size) == (elementData = this.elementData).length)elementData = grow();//赋值并且检查是否需要扩容System.arraycopy(elementData, index,elementData, index + 1,s - index);// 拷贝插入点前后的元素elementData[index] = element; // 插入点赋值size = s + 1;}
      

      addAll:添加集合中的元素

      扩容

      扩容判断

      if (s == elementData.length)则扩容
      

      这个是扩容的通用代码。
      记录了旧容量后,如果不是默认空数组,或者容量大于0则if成立。
      这里就是默认空数组和其他构造的空数组的区别了:

      如果是默认空数组则走初始容量为10的路线,否则则按照1.5倍扩容走

           /*** 增加容量以确保它至少可以容纳最小容量参数指定的元素数。** @param minCapacity 所需的最小容量* @throws OutOfMemoryError 如果最小容量小于零*/private Object[] grow(int minCapacity) {int oldCapacity = elementData.length;//获取旧容量if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {int newCapacity = ArraysSupport.newLength(oldCapacity,minCapacity - oldCapacity, /* 最小增长 */oldCapacity >> 1           /* 首选增长*/);//这个方法会从old的基础上,选取后面2个值的大的来增长。// 也就是,需要的容量和1.5倍比较return elementData = Arrays.copyOf(elementData, newCapacity);//拷贝旧的} else {return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];}}
      

      而一般性的,就是长度加一,调用上面的方法。

       private Object[] grow() {return grow(size + 1);}
      

      mount与迭代器

      其他常见方法

      //返回此列表中的元素数。
      public int size()//如果此列表不包含任何元素,则返回 true 。
      public boolean isEmpty()//如果此列表包含指定的元素,则返回true。更正式地说,当且仅当此列表包含至少一个元素eObjects.equals(o, e)时,返回 true .
      public boolean contains(Object o)//返回此列表中指定元素第一次出现的索引,如果此列表中不包含该元素,则返回 -1。更正式地说,返回最低索引,例如 Objects.equals(o, get(i)),如果没有这样的索引i,则返回 -1。
      public int indexOf(Object o)//返回此列表中指定元素最后一次出现的索引,如果此列表中不包含该元素,则返回 -1。更正式地说,返回最高索引,如果没有这样的索引iObjects.equals(o, get(i)),则返回 -1。public int lastIndexOf(Object o)

      不常见方法

      //将此实例的容量修剪为列表的 ArrayList 当前大小。
      public void trimToSize()  //如有必要,增加此 ArrayList 实例的容量,以确保它至少可以容纳最小容量参数指定的元素数。
      //形参:minCapacity – 所需的最小容量
      public void ensureCapacity(int minCapacity) //浅克隆
      public Object clone();

      不常见方法的源码和小介绍

      这是一个缩小空间的方法,把未使用的数组删掉。
      这个方法在ArrayList里面没有调用,但是在其他地方优化的时候还挺多的。
      在这里插入图片描述

          /*** 将此实例的容量修剪为列表的 ArrayList 当前大小。* 应用程序可以使用此操作来最小化实例的 ArrayList 存储*/public void trimToSize() {modCount++;if (size < elementData.length) {elementData = (size == 0)? EMPTY_ELEMENTDATA: Arrays.copyOf(elementData, size);}}
      

      没有调用的

      public void ensureCapacity(int minCapacity) {if (minCapacity > elementData.length&& !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA&& minCapacity <= DEFAULT_CAPACITY)) {modCount++;grow(minCapacity);}}
      
      	public Object clone() {try {ArrayList<?> v = (ArrayList<?>) super.clone();v.elementData = Arrays.copyOf(elementData, size);v.modCount = 0;return v;} catch (CloneNotSupportedException e) {// this shouldn't happen, since we are Cloneablethrow new InternalError(e);}}
      

      常见方法的源码和小介绍

      把这个放后面呢是因为简单应该看的人少。

      public int size() {return size;}
       public boolean isEmpty() {return size == 0;}
      
      public boolean contains(Object o) {return indexOf(o) >= 0;}
      
      	 public int indexOf(Object o) {return indexOfRange(o, 0, size);}int indexOfRange(Object o, int start, int end) {Object[] es = elementData;if (o == null) {for (int i = start; i < end; i++) {if (es[i] == null) {return i;}}} else {for (int i = start; i < end; i++) {if (o.equals(es[i])) {return i;}}}return -1;}
      
      	public int lastIndexOf(Object o) {return lastIndexOfRange(o, 0, size);}int lastIndexOfRange(Object o, int start, int end) {Object[] es = elementData;if (o == null) {for (int i = end - 1; i >= start; i--) {if (es[i] == null) {return i;}}} else {for (int i = end - 1; i >= start; i--) {if (o.equals(es[i])) {return i;}}}return -1;}
      

      积累面试题

      ArrayList是什么?可以用来干嘛?

      ArrayList是个动态数组,实现List接口,主要用来存储数据,只存储包装类。它的特点是:
      增删慢:每次删除元素,都需要更改数组长度、拷贝以及移动元素位置。
      查询快:由于数组在内存中是一块连续空间,因此可以根据地址+索引的方式快速获取对应位置上的元素。
      

      ArrayList 的默认长度

      在jdk8以前和jdk8以后稍有不同
      jdk8以前:创建就会初始数组长度,长度为10
      jdk8及以后:是懒加载,初始的时候为空数组,在第一次添加元素的时候扩容为10
      

      ArrayList如何扩容

      定好容量后,定好会把原来的数组元素拷贝到新数组中,再把指向原数的地址换到新数组。
      这个有2种扩容机制
      对于无参构造的集合:在第一次添加元素的时候会扩容到10,存满后按照1.5倍的进行扩容。如果一次添加了多个元素1.5倍放不下,则会按照实际需要的大小进行扩容。
      对于其他的构造:就没有扩容10的步骤了,按照max(1.5倍,实际大小)
      

      ArrayList频繁扩容导致性能下降该怎么办

      这时候我们可以估算需要的容量,使用
      ArrayList(int capacity)的有参构造来指定容量的空列表
      

      在测试中甚至有几个下图这样这样的比例运行了
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

      什么情况下你会使用ArrayList?什么时候你会选择LinkedList?

      多数情况下,当你遇到访问元素比插入或者是删除元素更加频繁的时候,你应该使用ArrayList。
      另外一方面,当你在某个特别的索引中,插入或者是删除元素更加频繁,或者你压根就不需要访问元素的时候,你会选择LinkedList。
      这里的主要原因是,在ArrayList中访问元素的最糟糕的时间复杂度是”1″,
      而在LinkedList中可能就是”n”了。
      在ArrayList中增加或者删除某个元素,通常会调用System.arraycopy方法,这是一种极为消耗资源的操作,因此,在频繁的插入或者是删除元素的情况下,LinkedList的性能会更加好一点。
      

      ArrayList的插入或删除一定比LinkedList慢吗

      大多数是的,但是不一定.
      如果删除靠前的元素arraylist需要拷贝后面的元素
      如果靠中间或者靠后,linkedlist找元素需要消耗很多的时间,而arraylist拷贝的元素会少一些
      arraylist取数真的太快了,linkedlist就算能从后面找,就算是取最后一个数,也慢了很多
      

      数组长度n=10000
      a=100
      b=n-a
      c=n/2
      可以看到:

      随机向中间添加,arraylist快
      add方法添加到最后,linkedlist完胜
      随机删除Arraylist快
      删除靠前元素:linkedlist快
      删除中间的,arralist快
      删除后面的,arralist快
      
      TestArrayList.testArrayListRandonAdd          thrpt    2    12289.462          ops/s
      TestArrayList.testLinkedListRandonAdd         thrpt    2    11362.013          ops/s
      TestArrayList.testArrayListRandonAddLast      thrpt    2    12820.688          ops/s
      TestArrayList.testLinkedListRandonAddLast     thrpt    2  2482660.154          ops/s
      TestArrayList.testArrayListRandonRemove       thrpt    2   207213.498          ops/s
      TestArrayList.testLinkedListRandonRemove      thrpt    2    11402.369          ops/s
      TestArrayList.testArrayListRemove100          thrpt    2   110029.496          ops/s
      TestArrayList.testLinkedListRemove100         thrpt    2  1036584.680          ops/s
      TestArrayList.testArrayListRemoveNDividing2   thrpt    2   205019.017          ops/s
      TestArrayList.testLinkedListRemoveNDividing2  thrpt    2     6156.114          ops/s
      TestArrayList.testArrayListRemoveN_100        thrpt    2  2064240.192          ops/s
      TestArrayList.testLinkedListRemoveN_100       thrpt    2  1072619.806          ops/s
      

      在这里插入图片描述
      在这里插入图片描述
      接下来下调参数
      n=1000
      a=10
      b=n-a
      c=n/2

      随机向中间添加,linkedlist快
      add方法添加到最后,linkedlist完胜
      随机删除Arraylist快
      删除靠前元素:linkedlist快
      删除中间的,arralist快
      删除后面的,linkedlist快
      
      Benchmark                                     Mode  Cnt  Score   Error  Units
      TestArrayList.testArrayListRandonAdd          avgt       0.912          us/op
      TestArrayList.testLinkedListRandonAdd         avgt       0.423          us/op
      TestArrayList.testArrayListRandonAddLast      avgt       0.788          us/op
      TestArrayList.testLinkedListRandonAddLast     avgt       0.042          us/op
      TestArrayList.testArrayListRandonRemove       avgt       0.194          us/op
      TestArrayList.testLinkedListRandonRemove      avgt       0.418          us/op
      TestArrayList.testArrayListRemove100          avgt       0.211          us/op
      TestArrayList.testLinkedListRemove100         avgt       0.043          us/op
      TestArrayList.testArrayListRemoveNDividing2   avgt       0.189          us/op
      TestArrayList.testLinkedListRemoveNDividing2  avgt       0.722          us/op
      TestArrayList.testArrayListRemoveN_100        avgt       0.151          us/op
      TestArrayList.testLinkedListRemoveN_100       avgt       0.039          us/op

      在这里插入图片描述

    相关文章:

    ArrayList源码分析(JDK17)

    ArrayList类简介类层次结构构造无参构造有参构造添加元素add&#xff1a;添加/插入一个元素addAll:添加集合中的元素扩容mount与迭代器其他常见方法不常见方法不常见方法的源码和小介绍常见方法的源码和小介绍积累面试题ArrayList是什么&#xff1f;可以用来干嘛&#xff1f;Ar…...

    数字IC/FPGA面试笔试准备(自用待填坑)

    文章目录 前言常见的IC问题数字电路基础问题Verilog & SV跨时钟域信号处理类综合与时序分析类低功耗方法STA(静态时序分析)RTL设计(包含手撕代码)总线问题AXIAPBAHB体系结构的问题RISCV的问题一些笔试选择题前言 这是实验室师兄面试过程中整理的面试和笔试题目,目前只有题…...

    基于多任务融合的圣女果采摘识别算法研究

    基于多任务融合的圣女果采摘识别算法研究 1、简介 本文主要解决圣女果生产销售环节中&#xff0c;现有的流程是采摘成熟的圣女果&#xff0c;再对采摘下的果实进行单独的品质分级&#xff0c;不仅费时费力&#xff0c;而且多增加一个环节&#xff0c;也增加了对果实的二次伤害…...

    又一个开源第一!飞桨联合百舸,Stable Diffusion推理速度遥遥领先

    AIGC(AI Generated Content)&#xff0c;即通过人工智能方法生成内容&#xff0c;是当前深度学习最热门的方向之一。其在绘画、写作等场景的应用也一直层出不穷&#xff0c;其中&#xff0c;AI绘画是大家关注和体验较多的方向。 Diffusion系列文生图模型可以实现AI绘画应用&…...

    数据链路层及交换机工作原理

    目录 一&#xff0c;帧格式 1.1 帧头类型字段的作用 1.2 MAC地址 1.3 MTU值 二&#xff0c;交换机工作原理 2.1 交换机的端口 2.2 端口状态 三&#xff0c;交换机基本工作模式及命令 3.1 交换机的工作模式&#xff1a; 3.2 命令 一&#xff0c;帧格式 其中类型是指&am…...

    VSCode 开发配置,一文搞定(持续更新中...)

    一、快速生成页面骨架 文件 > 首选项 > 配置用户代码片段 选择需要的代码片段或者创建一个新的&#xff0c;这里以 vue.json 举例&#xff1a; 下面为我配置的代码片段&#xff0c;仅供参考&#xff1a; {"Print to console": {"prefix": "…...

    全网最详细的(CentOS7)MySQL安装

    一、环境介绍 操作系统&#xff1a;CentOS 7 MySQL&#xff1a;5.7 二、MySQL卸载 查看软件 rpm -qa|grep mysql 卸载MySQL yum remove -y mysql mysql-libs mysql-common rm -rf /var/lib/mysql rm /etc/my.cnf 查看是否还有 MySQL 软件&#xff0c;有的话继续删除。 软件卸…...

    基于LSTM的文本情感分析(Keras版)

    一、前言 文本情感分析是自然语言处理中非常基本的任务&#xff0c;我们生活中有很多都是属于这一任务。比如购物网站的好评、差评&#xff0c;垃圾邮件过滤、垃圾短信过滤等。文本情感分析的实现方法也是多种多样的&#xff0c;可以使用传统的朴素贝叶斯、决策树&#xff0c;…...

    2023年全国最新机动车签字授权人精选真题及答案17

    百分百题库提供机动车签字授权人考试试题、机动车签字授权人考试预测题、机动车签字授权人考试真题、机动车签字授权人证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 三、多选题 1.注册登记安全检验时&#xff0c;送检乘用…...

    PowerShell远程代码执行漏洞(CVE-2022-41076)分析与复现

    漏洞概述PowerShell&#xff08;包括Windows PowerShell和PowerShell Core&#xff09;是微软公司开发的任务自动化和配置管理程序&#xff0c;最初只是一个 Windows 组件&#xff0c;由命令行 shell 和相关的脚本语言组成。后于2016年8月18日开源并提供跨平台支持。PowerShell…...

    Mybatis中的一级缓存和二级缓存

    Mybatis作为一款强大的ORM框架&#xff0c;其中也用到了缓存来加速查询&#xff0c;今天我们一起来探讨下。 Mybatis可以使用懒加载来提高查询的效率&#xff0c;并且可以通过缓存来提高查询的效率。其中包括有一级缓存和二级缓存。 一级缓存是sqlSession级别的缓存&#xff0c…...

    【Java】SpringBoot中实现异步编程

    前言 首先我们来看看在Spring中为什么要使用异步编程&#xff0c;它能解决什么问题&#xff1f; 什么是异步&#xff1f; 首先我们先来看看一个同步的用户注册例子&#xff0c;流程如下&#xff1a; 异步的方式如下&#xff1a; 在用户注册后将成功结果返回&#xff0c;…...

    ASCII 文件与 TIFF 文件互转(Python 实现)(2023/03/09)

    ASCII 文件与 TIFF 文件互转&#xff08;Python 实现&#xff09; 文章目录ASCII 文件与 TIFF 文件互转&#xff08;Python 实现&#xff09;1. 环境1.1 Linux1.2 Windows2. 代码1. 环境 1.1 Linux $ pip3 install --index-url https://mirrors.aliyun.com/pypi/simple --tru…...

    思科模拟器 | 交换机与路由器的配置汇总【收藏备用】

    文章目录一、vlan配置【实现同一vlan的主机通信】1、基本配置和接线2、vlan配置与端口连接3、测试连接二、truck配置【实现连接在不同交换机上的同一vlan的主机通信】1、基本配置和接线2、vlan配置与端口连接3、打truck做连接3、测试连接三、静态路由配置1、自定义IP地址2、基本…...

    电子台账:软件运行环境要求与功能特点

    1 运行环境要求为满足大部分应用环境&#xff0c;软件开发时综合考虑各种各种不同因素影星&#xff0c;包括&#xff1a;操作系统、硬件、辅助软件、安装、运行、补丁、数据库、网络、人员等因素。目前台账软件需求为&#xff1a;操作系统&#xff1a;目前能运行的任意版本wind…...

    计算机科学导论笔记(六)

    目录 八、算法 8.1 概念 8.1.1 非正式定义 8.1.2 示例 8.1.3 定义动作 8.1.4 细化 8.1.5 泛化 8.2 三种结构 8.2.1 顺序 8.2.2 判断 8.2.3 循环 8.3 算法的表示 8.3.1 UML 8.3.2 伪代码 8.4 更正式的定义 8.5 基本算法 8.5.1 求和 8.5.2 求积 8.5.3 最大和最…...

    嵌入式从业10年,聊聊我对工业互联网和消费物联网的看法 | 文末赠书4本

    嵌入式从业10年&#xff0c;聊聊我对工业互联网和消费物联网的看法 工业互联网和消费物联网&#xff0c;有何异常点&#xff1f;本文&#xff0c;博主将结合自己的亲身经历&#xff0c;现身说法&#xff0c;聊聊博主对工业互联网和消费物联网的看法。 文章目录1 写在前面2 我眼…...

    python的django框架从入门到熟练【保姆式教学】第一篇

    当今&#xff0c;Python已成为最受欢迎的编程语言之一。而Django是一个基于Python的Web框架&#xff0c;它能够帮助你快速、高效地开发Web应用程序。如果你是一名初学者&#xff0c;学习Django框架可能会让你感到有些困惑。不过&#xff0c;不用担心&#xff0c;我们将为你提供…...

    浏览记录或者购物车的去重处理

    saveHistory(){// 获取缓存数据let historyArr uni.getStorageSync(historyArr) || []//需要添加的数据let item{id:this.detail.id,classid:this.detail.classid,title:this.detail.title,picurl:this.detail.picurl,looktime:parseTime(Date.now())};// forEach和findIndex的…...

    Ubantu docker学习笔记(二)拉取构建,属于你的容器

    文章目录一、拉取启动容器二、本地镜像初解三、构建镜像3.1使用docker commit构建镜像切换阿里镜像3.2使用dockerfile构建镜像四、总个结吧这里的话&#xff0c;就详细说说小唐对于容器的配置&#xff0c;对了&#xff01;小唐参考的书籍是Linux容器云实战&#xff01;&#xf…...

    基于FPGA的PID算法学习———实现PID比例控制算法

    基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

    Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

    一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

    ElasticSearch搜索引擎之倒排索引及其底层算法

    文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

    C++ 求圆面积的程序(Program to find area of a circle)

    给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

    ios苹果系统,js 滑动屏幕、锚定无效

    现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

    【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

    1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

    使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

    🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

    Kafka入门-生产者

    生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

    【Linux】Linux 系统默认的目录及作用说明

    博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

    从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

    作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...