Java 集合系列:Vector源码深入解析

news2024/12/23 7:09:48

概论

学完ArrayList和LinkedList之后,我们接着学习Vector。学习方式还是和之前一样,先对Vector有个整体认识,然后再学习它的源码;最后再通过实例来学会使用它。

第1部分 Vector介绍

Vector简介

Vector 是矢量队列,它是JDK1.0版本添加的类。继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口。 Vector 继承了AbstractList,实现了List;所以,它是一个队列,支持相关的添加、删除、修改、遍历等功能。 Vector 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。 Vector 实现了Cloneable接口,即实现clone()函数。它能被克隆。

和ArrayList不同,Vector中的操作是线程安全的。

Vector的构造函数

Vector共有4个构造函数
// 默认构造函数
Vector()

// capacity是Vector的默认容量大小。当由于增加数据导致容量增加时,每次容量会增加一倍。
Vector(int capacity)

// capacity是Vector的默认容量大小,capacityIncrement是每次Vector容量增加时的增量值。
Vector(int capacity, int capacityIncrement)

// 创建一个包含collection的Vector
Vector(Collection<? extends E> collection) 

Vector的API

synchronized booleanadd(E object) void add(int location, E object)
synchronized booleanaddAll(Collection<? extends E> collection)
synchronized booleanaddAll(int location, Collection<? extends E> collection)
synchronized void addElement(E object)
synchronized intcapacity() void clear()
synchronized Object clone() booleancontains(Object object)
synchronized booleancontainsAll(Collection<?> collection)
synchronized void copyInto(Object[] elements)
synchronized EelementAt(int location) Enumeration<E> elements()
synchronized void ensureCapacity(int minimumCapacity)
synchronized booleanequals(Object object)
synchronized EfirstElement() Eget(int location)
synchronized inthashCode()
synchronized intindexOf(Object object, int location) intindexOf(Object object)
synchronized void insertElementAt(E object, int location)
synchronized booleanisEmpty()
synchronized ElastElement()
synchronized intlastIndexOf(Object object, int location)
synchronized intlastIndexOf(Object object)
synchronized Eremove(int location) booleanremove(Object object)
synchronized booleanremoveAll(Collection<?> collection)
synchronized void removeAllElements()
synchronized booleanremoveElement(Object object)
synchronized void removeElementAt(int location)
synchronized booleanretainAll(Collection<?> collection)
synchronized Eset(int location, E object)
synchronized void setElementAt(E object, int location)
synchronized void setSize(int length)
synchronized intsize()
synchronized List<E>subList(int start, int end)
synchronized <T> T[]toArray(T[] contents)
synchronized Object[] toArray()
synchronized String toString()
synchronized void trimToSize() 

第2部分 Vector数据结构

Vector的继承关系

java.lang.Object ↳ java.util.AbstractCollection<E> ↳ java.util.AbstractList<E> ↳ java.util.Vector<E>

public class Vector<E>extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {} 

Vector与Collection关系如下图:

Vector的数据结构和ArrayList差不多,它包含了3个成员变量:elementData , elementCount, capacityIncrement

(01) elementData 是"Object[]类型的数组",它保存了添加到Vector中的元素。elementData是个动态数组,如果初始化Vector时,没指定动态数组的>大小,则使用默认大小10。随着Vector中元素的增加,Vector的容量也会动态增长,capacityIncrement是与容量增长相关的增长系数,具体的增长方式,请参考源码分析中的ensureCapacity()函数。

(02) elementCount 是动态数组的实际大小。

(03) capacityIncrement 是动态数组的增长系数。如果在创建Vector时,指定了capacityIncrement的大小;则,每次当Vector中动态数组容量增加时>,增加的大小都是capacityIncrement。

第3部分 Vector源码解析(基于JDK1.6.0_45)

为了更了解Vector的原理,下面对Vector源码代码作出分析。

package java.util;

public class Vector<E>extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{ // 保存Vector中数据的数组protected Object[] elementData;// 实际数据的数量protected int elementCount;// 容量增长系数protected int capacityIncrement;// Vector的序列版本号private static final long serialVersionUID = -2767605614048989439L;// Vector构造函数。默认容量是10。public Vector() {this(10);}// 指定Vector容量大小的构造函数public Vector(int initialCapacity) {this(initialCapacity, 0);}// 指定Vector"容量大小"和"增长系数"的构造函数public Vector(int initialCapacity, int capacityIncrement) {super();if (initialCapacity < 0)throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);// 新建一个数组,数组容量是initialCapacitythis.elementData = new Object[initialCapacity];// 设置容量增长系数this.capacityIncrement = capacityIncrement;}// 指定集合的Vector构造函数。public Vector(Collection<? extends E> c) {// 获取“集合(c)”的数组,并将其赋值给elementDataelementData = c.toArray();// 设置数组长度elementCount = elementData.length;// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, elementCount, Object[].class);}// 将数组Vector的全部元素都拷贝到数组anArray中public synchronized void copyInto(Object[] anArray) {System.arraycopy(elementData, 0, anArray, 0, elementCount);}// 将当前容量值设为 =实际元素个数public synchronized void trimToSize() {modCount++;int oldCapacity = elementData.length;if (elementCount < oldCapacity) {elementData = Arrays.copyOf(elementData, elementCount);}}// 确认“Vector容量”的帮助函数private void ensureCapacityHelper(int minCapacity) {int oldCapacity = elementData.length;// 当Vector的容量不足以容纳当前的全部元素,增加容量大小。// 若 容量增量系数>0(即capacityIncrement>0),则将容量增大当capacityIncrement// 否则,将容量增大一倍。if (minCapacity > oldCapacity) {Object[] oldData = elementData;int newCapacity = (capacityIncrement > 0) ?(oldCapacity + capacityIncrement) : (oldCapacity * 2);if (newCapacity < minCapacity) {newCapacity = minCapacity;}elementData = Arrays.copyOf(elementData, newCapacity);}}// 确定Vector的容量。public synchronized void ensureCapacity(int minCapacity) {// 将Vector的改变统计数+1modCount++;ensureCapacityHelper(minCapacity);}// 设置容量值为 newSizepublic synchronized void setSize(int newSize) {modCount++;if (newSize > elementCount) {// 若 "newSize 大于 Vector容量",则调整Vector的大小。ensureCapacityHelper(newSize);} else {// 若 "newSize 小于/等于 Vector容量",则将newSize位置开始的元素都设置为nullfor (int i = newSize ; i < elementCount ; i++) {elementData[i] = null;}}elementCount = newSize;}// 返回“Vector的总的容量”public synchronized int capacity() {return elementData.length;}// 返回“Vector的实际大小”,即Vector中元素个数public synchronized int size() {return elementCount;}// 判断Vector是否为空public synchronized boolean isEmpty() {return elementCount == 0;}// 返回“Vector中全部元素对应的Enumeration”public Enumeration<E> elements() {// 通过匿名类实现Enumerationreturn new Enumeration<E>() {int count = 0;// 是否存在下一个元素public boolean hasMoreElements() {return count < elementCount;}// 获取下一个元素public E nextElement() {synchronized (Vector.this) {if (count < elementCount) {return (E)elementData[count++];}}throw new NoSuchElementException("Vector Enumeration");}};}// 返回Vector中是否包含对象(o)public boolean contains(Object o) {return indexOf(o, 0) >= 0;}// 从index位置开始向后查找元素(o)。// 若找到,则返回元素的索引值;否则,返回-1public synchronized int indexOf(Object o, int index) {if (o == null) {// 若查找元素为null,则正向找出null元素,并返回它对应的序号for (int i = index ; i < elementCount ; i++)if (elementData[i]==null)return i;} else {// 若查找元素不为null,则正向找出该元素,并返回它对应的序号for (int i = index ; i < elementCount ; i++)if (o.equals(elementData[i]))return i;}return -1;}// 查找并返回元素(o)在Vector中的索引值public int indexOf(Object o) {return indexOf(o, 0);}// 从后向前查找元素(o)。并返回元素的索引public synchronized int lastIndexOf(Object o) {return lastIndexOf(o, elementCount-1);}// 从后向前查找元素(o)。开始位置是从前向后的第index个数;// 若找到,则返回元素的“索引值”;否则,返回-1。public synchronized int lastIndexOf(Object o, int index) {if (index >= elementCount)throw new IndexOutOfBoundsException(index + " >= "+ elementCount);if (o == null) {// 若查找元素为null,则反向找出null元素,并返回它对应的序号for (int i = index; i >= 0; i--)if (elementData[i]==null)return i;} else {// 若查找元素不为null,则反向找出该元素,并返回它对应的序号for (int i = index; i >= 0; i--)if (o.equals(elementData[i]))return i;}return -1;}// 返回Vector中index位置的元素。// 若index月结,则抛出异常public synchronized E elementAt(int index) {if (index >= elementCount) {throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);}return (E)elementData[index];}// 获取Vector中的第一个元素。// 若失败,则抛出异常!public synchronized E firstElement() {if (elementCount == 0) {throw new NoSuchElementException();}return (E)elementData[0];}// 获取Vector中的最后一个元素。// 若失败,则抛出异常!public synchronized E lastElement() {if (elementCount == 0) {throw new NoSuchElementException();}return (E)elementData[elementCount - 1];}// 设置index位置的元素值为objpublic synchronized void setElementAt(E obj, int index) {if (index >= elementCount) {throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);}elementData[index] = obj;}// 删除index位置的元素public synchronized void removeElementAt(int index) {modCount++;if (index >= elementCount) {throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);} else if (index < 0) {throw new ArrayIndexOutOfBoundsException(index);}int j = elementCount - index - 1;if (j > 0) {System.arraycopy(elementData, index + 1, elementData, index, j);}elementCount--;elementData[elementCount] = null; /* to let gc do its work */}// 在index位置处插入元素(obj)public synchronized void insertElementAt(E obj, int index) {modCount++;if (index > elementCount) {throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount);}ensureCapacityHelper(elementCount + 1);System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);elementData[index] = obj;elementCount++;}// 将“元素obj”添加到Vector末尾public synchronized void addElement(E obj) {modCount++;ensureCapacityHelper(elementCount + 1);elementData[elementCount++] = obj;}// 在Vector中查找并删除元素obj。// 成功的话,返回true;否则,返回false。public synchronized boolean removeElement(Object obj) {modCount++;int i = indexOf(obj);if (i >= 0) {removeElementAt(i);return true;}return false;}// 删除Vector中的全部元素public synchronized void removeAllElements() {modCount++;// 将Vector中的全部元素设为nullfor (int i = 0; i < elementCount; i++)elementData[i] = null;elementCount = 0;}// 克隆函数public synchronized Object clone() {try {Vector<E> v = (Vector<E>) super.clone();// 将当前Vector的全部元素拷贝到v中v.elementData = Arrays.copyOf(elementData, elementCount);v.modCount = 0;return v;} catch (CloneNotSupportedException e) {// this shouldn't happen, since we are Cloneablethrow new InternalError();}}// 返回Object数组public synchronized Object[] toArray() {return Arrays.copyOf(elementData, elementCount);}// 返回Vector的模板数组。所谓模板数组,即可以将T设为任意的数据类型public synchronized <T> T[] toArray(T[] a) {// 若数组a的大小 < Vector的元素个数;// 则新建一个T[]数组,数组大小是“Vector的元素个数”,并将“Vector”全部拷贝到新数组中if (a.length < elementCount)return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());// 若数组a的大小 >= Vector的元素个数;// 则将Vector的全部元素都拷贝到数组a中。System.arraycopy(elementData, 0, a, 0, elementCount);if (a.length > elementCount)a[elementCount] = null;return a;}// 获取index位置的元素public synchronized E get(int index) {if (index >= elementCount)throw new ArrayIndexOutOfBoundsException(index);return (E)elementData[index];}// 设置index位置的值为element。并返回index位置的原始值public synchronized E set(int index, E element) {if (index >= elementCount)throw new ArrayIndexOutOfBoundsException(index);Object oldValue = elementData[index];elementData[index] = element;return (E)oldValue;}// 将“元素e”添加到Vector最后。public synchronized boolean add(E e) {modCount++;ensureCapacityHelper(elementCount + 1);elementData[elementCount++] = e;return true;}// 删除Vector中的元素opublic boolean remove(Object o) {return removeElement(o);}// 在index位置添加元素elementpublic void add(int index, E element) {insertElementAt(element, index);}// 删除index位置的元素,并返回index位置的原始值public synchronized E remove(int index) {modCount++;if (index >= elementCount)throw new ArrayIndexOutOfBoundsException(index);Object oldValue = elementData[index];int numMoved = elementCount - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index, numMoved);elementData[--elementCount] = null; // Let gc do its workreturn (E)oldValue;}// 清空Vectorpublic void clear() {removeAllElements();}// 返回Vector是否包含集合cpublic synchronized boolean containsAll(Collection<?> c) {return super.containsAll(c);}// 将集合c添加到Vector中public synchronized boolean addAll(Collection<? extends E> c) {modCount++;Object[] a = c.toArray();int numNew = a.length;ensureCapacityHelper(elementCount + numNew);// 将集合c的全部元素拷贝到数组elementData中System.arraycopy(a, 0, elementData, elementCount, numNew);elementCount += numNew;return numNew != 0;}// 删除集合c的全部元素public synchronized boolean removeAll(Collection<?> c) {return super.removeAll(c);}// 删除“非集合c中的元素”public synchronized boolean retainAll(Collection<?> c){return super.retainAll(c);}// 从index位置开始,将集合c添加到Vector中public synchronized boolean addAll(int index, Collection<? extends E> c) {modCount++;if (index < 0 || index > elementCount)throw new ArrayIndexOutOfBoundsException(index);Object[] a = c.toArray();int numNew = a.length;ensureCapacityHelper(elementCount + numNew);int numMoved = elementCount - index;if (numMoved > 0)System.arraycopy(elementData, index, elementData, index + numNew, numMoved);System.arraycopy(a, 0, elementData, index, numNew);elementCount += numNew;return numNew != 0;}// 返回两个对象是否相等public synchronized boolean equals(Object o) {return super.equals(o);}// 计算哈希值public synchronized int hashCode() {return super.hashCode();}// 调用父类的toString()public synchronized String toString() {return super.toString();}// 获取Vector中fromIndex(包括)到toIndex(不包括)的子集public synchronized List<E> subList(int fromIndex, int toIndex) {return Collections.synchronizedList(super.subList(fromIndex, toIndex), this);}// 删除Vector中fromIndex到toIndex的元素protected synchronized void removeRange(int fromIndex, int toIndex) {modCount++;int numMoved = elementCount - toIndex;System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved);// Let gc do its workint newElementCount = elementCount - (toIndex-fromIndex);while (elementCount != newElementCount)elementData[--elementCount] = null;}// java.io.Serializable的写入函数private synchronized void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException {s.defaultWriteObject();}
} 

总结: (01) Vector实际上是通过一个数组去保存数据的。当我们构造Vecotr时;若使用默认构造函数,则Vector的默认容量大小是10。 (02) 当Vector容量不足以容纳全部元素时,Vector的容量会增加。若容量增加系数 >0,则将容量的值增加“容量增加系数”;否则,将容量大小增加一倍。 (03) Vector的克隆函数,即是将全部元素克隆到一个数组中。

第4部分 Vector遍历方式

Vector支持4种遍历方式。建议使用下面的第二种去遍历Vector,因为效率问题。

(01) 第一种,通过迭代器遍历。即通过Iterator去遍历。

Integer value = null;
int size = vec.size();
for (int i=0; i<size; i++) {value = (Integer)vec.get(i); 
} 

(02) 第二种,随机访问,通过索引值去遍历。 由于Vector实现了RandomAccess接口,它支持通过索引值去随机访问元素。

Integer value = null;
int size = vec.size();
for (int i=0; i<size; i++) {value = (Integer)vec.get(i); 
} 

(03) 第三种,另一种for循环。如下:

Integer value = null;
for (Integer integ:vec) {value = integ;
} 

(04) 第四种,Enumeration遍历。如下:

Integer value = null;
Enumeration enu = vec.elements();
while (enu.hasMoreElements()) {value = (Integer)enu.nextElement();
} 

测试这些遍历方式效率的代码如下:

import java.util.*;

/*
 * @desc Vector遍历方式和效率的测试程序。
 *
 * @author skywang
 */
public class VectorRandomAccessTest {public static void main(String[] args) {Vector vec= new Vector();for (int i=0; i<100000; i++)vec.add(i);iteratorThroughRandomAccess(vec) ;iteratorThroughIterator(vec) ;iteratorThroughFor2(vec) ;iteratorThroughEnumeration(vec) ;}private static void isRandomAccessSupported(List list) {if (list instanceof RandomAccess) {System.out.println("RandomAccess implemented!");} else {System.out.println("RandomAccess not implemented!");}}public static void iteratorThroughRandomAccess(List list) {long startTime;long endTime;startTime = System.currentTimeMillis();for (int i=0; i<list.size(); i++) {list.get(i);}endTime = System.currentTimeMillis();long interval = endTime - startTime;System.out.println("iteratorThroughRandomAccess:" + interval+" ms");}public static void iteratorThroughIterator(List list) {long startTime;long endTime;startTime = System.currentTimeMillis();for(Iterator iter = list.iterator(); iter.hasNext(); ) {iter.next();}endTime = System.currentTimeMillis();long interval = endTime - startTime;System.out.println("iteratorThroughIterator:" + interval+" ms");}public static void iteratorThroughFor2(List list) {long startTime;long endTime;startTime = System.currentTimeMillis();for(Object obj:list);endTime = System.currentTimeMillis();long interval = endTime - startTime;System.out.println("iteratorThroughFor2:" + interval+" ms");}public static void iteratorThroughEnumeration(Vector vec) {long startTime;long endTime;startTime = System.currentTimeMillis();for(Enumeration enu = vec.elements(); enu.hasMoreElements(); ) {enu.nextElement();}endTime = System.currentTimeMillis();long interval = endTime - startTime;System.out.println("iteratorThroughEnumeration:" + interval+" ms");}
} 

运行结果:

iteratorThroughRandomAccess:6 ms iteratorThroughIterator:9 ms iteratorThroughFor2:8 ms iteratorThroughEnumeration:7 ms

总结: 遍历Vector,使用索引的随机访问方式最快,使用迭代器最慢。

第5部分 Vector示例

下面通过示例学习如何使用Vector

import java.util.Vector;
import java.util.List;
import java.util.Iterator;
import java.util.Enumeration;

/**
 * @desc Vector测试函数:遍历Vector和常用API 
 *
 * @author skywang
 */
public class VectorTest {public static void main(String[] args) {// 新建VectorVector vec = new Vector();// 添加元素vec.add("1");vec.add("2");vec.add("3");vec.add("4");vec.add("5");// 设置第一个元素为100vec.set(0, "100");// 将“500”插入到第3个位置vec.add(2, "300");System.out.println("vec:"+vec);// (顺序查找)获取100的索引System.out.println("vec.indexOf(100):"+vec.indexOf("100"));// (倒序查找)获取100的索引System.out.println("vec.lastIndexOf(100):"+vec.lastIndexOf("100"));// 获取第一个元素System.out.println("vec.firstElement():"+vec.firstElement());// 获取第3个元素System.out.println("vec.elementAt(2):"+vec.elementAt(2));// 获取最后一个元素System.out.println("vec.lastElement():"+vec.lastElement());// 获取Vector的大小System.out.println("size:"+vec.size());// 获取Vector的总的容量System.out.println("capacity:"+vec.capacity());// 获取vector的“第2”到“第4”个元素System.out.println("vec 2 to 4:"+vec.subList(1, 4));// 通过Enumeration遍历VectorEnumeration enu = vec.elements();while(enu.hasMoreElements())System.out.println("nextElement():"+enu.nextElement());Vector retainVec = new Vector();retainVec.add("100");retainVec.add("300");// 获取“vec”中包含在“retainVec中的元素”的集合System.out.println("vec.retain():"+vec.retainAll(retainVec));System.out.println("vec:"+vec);// 获取vec对应的String数组String[] arr = (String[]) vec.toArray(new String[0]);for (String str:arr)System.out.println("str:"+str);// 清空Vector。clear()和removeAllElements()一样!vec.clear();
//vec.removeAllElements();// 判断Vector是否为空System.out.println("vec.isEmpty():"+vec.isEmpty());} 
} 

运行结果:

vec:[100, 2, 300, 3, 4, 5] vec.indexOf(100):0 vec.lastIndexOf(100):0 vec.firstElement():100 vec.elementAt(2):300 vec.lastElement():5 size:6 capacity:10 vec 2 to 4:[2, 300, 3] nextElement():100 nextElement():2 nextElement():300 nextElement():3 nextElement():4 nextElement():5 vec.retain():true vec:[100, 300] str:100 str:300 vec.isEmpty():true

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

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

相关文章

java服装商城购物商场项目源码

简介 Java基于ssm开发的服装商城&#xff0c;用户可以浏览商品和特价商品&#xff0c;加入购物车&#xff0c;直接下单支付&#xff0c;在我的个人中心里可以管理自己的订单&#xff0c;收货地址&#xff0c;编辑资料等。管理员可以发布商品&#xff0c;上下架商品&#xff0c…

Neo4j详细介绍及使用教程

文章目录一、Neo4j介绍1.Neo4j简介2.图数据库简介3.Neo4j的优缺点4.Neo4j的常见应用场景二、使用教程1.下载安装2.数据插入和查询(1)基本概念(2)基本语法Ⅰ.CREATE操作——创建Ⅱ.MERGE——创建或更新Ⅲ.Match操作——查找指定的图数据Ⅳ.DELETE操作——删除节点3.JAVA实战一、…

FPGA之VGA/LCD数字时钟显示

文章目录前言一、LCD显示控制1.LCD显示一个字符2.LCD显示多个字符二、数字时钟输出1.数字时钟2.十进制数据拆分BCD码三、按键检测及LCD驱动1.按键检测2.LCD驱动四、总结前言 软件实现了在4.3寸LCD左上角显示一个数字时钟&#xff0c;效果如下图所示。本文针对VGA/LCD控制时许有…

leetcode:2103. 环和杆(python3解法)

难度&#xff1a;简单 总计有 n 个环&#xff0c;环的颜色可以是红、绿、蓝中的一种。这些环分布穿在 10 根编号为 0 到 9 的杆上。 给你一个长度为 2n 的字符串 rings &#xff0c;表示这 n 个环在杆上的分布。rings 中每两个字符形成一个 颜色位置对 &#xff0c;用于描述每个…

makefile 入门

make常用选项 # make 默认在当前目录中寻找GUNmakefile,makefile,Makefile的文件作为make的输入文件 # -f 可以指定默认的输入文件名,如: -f MyMakefile # -v 显示make版本号 # -n 只输出命令,但不执行,一般用于测试 # -s 只执行命令,但不显示具体命令,与在命令中使用作用一样…

第四十四讲:神州防火墙双机热备配置

两台防火墙硬件型号和软件版本都完全相同&#xff0c;为了避免防火墙不堪重负而宕机引起网络中断&#xff0c;可以考虑应用双机热备&#xff08;HA&#xff09;解决方案。双机热备能够把两台防火墙构成一个工作组&#xff0c;一主一备&#xff0c;保证数据通信畅通&#xff0c;…

【实际开发01】- 单元测试 ( 追求正确性 )

目录 0. 单元测试 概念 / 解析 1. 为什么要进行单元测试 1. JUnit ~ Test 2. IDEA 中使用 junit 单元测试 , 不能使用 Scanner 的解决方法 3. Junit 测试 Tutorial 1. daiding 4. Test 修饰的方法必须 public 1. validatePublicVoidNoArgMethods(Test.class, false, er…

功率二极管的损耗分析和选型原则

功率二极管的损耗分析和选型原则 tip&#xff1a;参考网上资料&#xff0c;学习为主 1.二极管的分类 2.二极管的损耗组成 3.二级管的损耗分析 4.应用实例1.Flyback电源电路二极管损耗计算 5.实例应用2.BOOST电路二极管损耗计算 6.实例应用3.大功率整流桥二极管参数计算 7.选型…

sqli-labs 5~6 多命通关攻略

sqli-labs 5~6 多命通关攻略描述判断注入类型正常输入不正常输入错误输入判断 SQL 查询结果的列数猜测 SQL 查询结果中的列数为两列猜测 SQL 查询结果中的列数为三列猜测 SQL 查询结果中的列数为四列爆破方式的可行性函数 UpdateXML()爆破&#xff08;报错注入&#xff09;爆破…

农业智能化进入“刚需时代 ” ,维视智造机器视觉实验室赋能新农科人才培养

1、传统农业数字化转型 新农科人才急需紧缺数千年来&#xff0c;农业是我国立国基础&#xff0c;农业兴衰关系到国家的命运。在大力推动乡村振兴的背景下&#xff0c;高校作为强农兴农的“国之重器”&#xff0c;在培育“农”的传人、新农科建设方面扮演着不可替代的角色。世界…

C++入门——内联函数、extern “C“

一. 内联函数 1.概念及分析 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调 用建立栈帧的开销&#xff0c;内联函数提升程序运行的效率。 int Add(int a, int b) {int c a b;return c; }int main() {int re…

聚焦技术创新实力,时序数据库 TDengine 荣登中国技术先锋年度评选两大榜单

2023 年 1 月 5 日&#xff0c;中国技术先锋年度评选 | 2022 中国最受开发者欢迎的技术活动榜单正式发布。作为中国领先的新一代开发者社区&#xff0c;SegmentFault 思否依托社区活动板块及全站数百万开发者用户行为数据&#xff0c;及活动规模、内容好评度、行业综合影响力指…

Go语言设计与实现 --调度器(详细介绍)

GMP和GM模型 先来一张图&#xff1a; G(Goroutine)&#xff1a;代表Go 协程Goroutine&#xff0c;存储了 Goroutine 的执行栈信息、Goroutine 状态以及 Goroutine 的任务函数等。G的数量无限制&#xff0c;理论上只受内存的影响&#xff0c;创建一个 G 的初始栈大小为2-4K&…

vue项目安装使用element_UI

安装element_UI之前需要安装VUE脚手架框架! 第一步: 在Vscode 随意打开一个文件夹,在集成终端打开 npm i -g vue/cli (检测: vue -V) 第二步:新建一个文件夹,并且在集成终端打开安装VUE脚手架 需要输入命令: vue create yan6 //yan6 为自定义文件名 1: 选第三个自定义 2: 将…

SpringBoot缓存数据(官方案例)

在线文档项目结构 1.源码克隆&#xff1a;git clone https://github.com/spring-guides/gs-caching.git 2.包含两个项目initial和complete&#xff0c;initial可以根据文档练习完善&#xff0c;complete是完整项目 3.功能描述&#xff1a;构建应用程序&#xff0c;在图书存储库…

JAVA并发编程工具篇--1理解线程池任务的执行和线程的销毁

前言&#xff1a;在编程中我们为什么要使用线程池&#xff0c;线程池中的线程是怎么执行任务的&#xff0c;线程池中的线程是如何复用和销毁的&#xff1b; 1 什么是线程池&#xff1a; 提前创建一些线程放到一个地方&#xff0c;使用的时候直接获取&#xff0c;避免频繁的创建…

CalDAV网页客户端AgenDAV

什么是 AgenDAV &#xff1f; AgenDAV 是一个类似于 Google 日历的 CalDAV 网络客户端&#xff0c;具有 AJAX 界面&#xff0c;允许用户管理自己的日历和共享的日历。 注意事项 AgenDAV依赖于 CalDAV 服务器&#xff08;Bakal、DAViCal 等&#xff09;&#xff0c;所以需要先安…

软件测试员在面试中常遇问题

目前&#xff0c;疫情已经逐渐得到了控制&#xff0c;各行各业都掀起了复工大潮。与此同时&#xff0c;软件测试的招聘需求也随着复工的开始而变得紧急起来&#xff0c;而求职者应该怎样抓住机会进行应聘呢&#xff1f;首先最重要的就是多刷面试题&#xff0c;这样才能才面试过…

CSS权威指南(五)字体

文章目录1.字体族2.font-face3.字重&#xff08;font-weight&#xff09;4.字号&#xff08;font-size&#xff09;5.字形&#xff08;font-style&#xff09;6.字体拉伸&#xff08;font-stretch&#xff09;7.字距&#xff08;font-kerning&#xff09;8.字体变形&#xff08…

Python 办公自动化,全网最全整理来了!拒绝无效率加班!

大家好&#xff0c;今天给大家分享一篇 Python 自动化办公干货&#xff0c;整整42个实战项目案例。每一个项目案例都有详细的视频讲解&#xff0c;是一套非常全面的Python自动化办公项目&#xff0c;建议大家收藏后学习&#xff0c;梳理不易&#xff0c;记得点赞支持。详细目录…