Java基础16(集合 List)

目录

一、什么是集合?

二、集合接口

三、List集合

1. ArrayList容器类

1.1 常用方法

1.1.1 增加

1.1.2 查找

int  size() 

E  get(int index) 

int indexOf(Object  c) 

boolean contains(Object  c)

boolean  isEmpty()

List  SubList(int fromindex,int  toIndex)

boolean equals(Object o)

1.1.3 修改

E set(int index, E element)

1.1.4 删除

 boolean removeAll(Collection c)--- 差集

boolean retainAll(Collection c)   --交集 

1.1.5 其他方法

clone()  

sort()

转换为数组


一、什么是集合?

        什么是集合?集合就是“由若干个确定的元素所构成的整体”,在程序中,一般代表保存若干个元素(数据)的某种容器类。在数学中,我们经常遇到集合的概念。例如:


●有限集合:

  • 一个班所有的同学构成的集合;
  • 一个网站所有的商品构成的集合;
  • ...

●无限集合:

  • 全体自然数集合:1,2,3,……
  • 有理数集合;
  • 实数集合;
  • ...


为什么要在计算机中引入集合呢?这是为了便于处理一组类似的数据,例如:

  • 计算所有同学的总成绩和平均成绩;
  • 列举所有的商品名称和价格;
  • ……


        在Java中,如果一个Java对象可以在内部持有(保存)若干其他Java对象,并对外提供访问接口,我们把这种Java对象的容器称为集合。很显然,Java的数组也可以看作是一种集合:

        既然Java提供了数组这种数据类型,可以充当集合,那么,我们为什么还需要其他集合类?这是因为数组有如下限制:

  • 长度开始时必须指定,且一旦指定,不能更改;即数组长度很难扩容
  • 保存的必须为同一类型的元素;
  • 数组的方法和功能不完善,查看数组中的具体长度,只有length属性知道内存大小,不知道具体的元素个数。 

public static void main(String[] args) {String[] menu = new String[10];menu[0] = "麻婆豆腐";menu[1] = "麻辣烫";menu[2] = "null";System.out.println(menu.length);//10ArrayList<String> arrayList = new ArrayList<String>();for (int i = 0; i < 3; i++) {arrayList.add("麻婆豆腐");arrayList.add("麻辣烫");arrayList.add("null");
//			arrayList.add( 12 );
//			arrayList.add( 12.23 );
//			arrayList.add( true );
//			arrayList.add(new Date());}System.out.println(arrayList);//[麻婆豆腐, 麻辣烫, null, 麻婆豆腐, 麻辣烫, null, 麻婆豆腐, 麻辣烫, null]System.out.println(arrayList.size());//9}


因此,我们需要各种不同类型的集合类来处理不同的数据,例如:

  • 可变大小的顺序链表;
  • 保证无重复元素的集合;
  • ...

二、集合接口

        Java标准库自带的java.util包提供了集合相关的接口和实现类:Collection接口,它是除Map接口外所有其他集合类的根接口。

Collection接口:collection接口是单例集合的跟接口,英文含义集中、收集

单列集合是将数据进行一个一个的存储,存储的是值

Java的java.util包主要提供了以下三种类型的集合:

  • List:一种有序列表的集合;
  • Set:一种保证没有重复元素的集合;
  • Map:一种通过键值(key-value)查找的映射表集合,例如,根据Student的name查找对应Student的Map。

        Java集合的设计有几个特点:首先实现了接口和实现类相分离,例如,有序表的接口是List,具体的实现类有ArrayList,LinkedList等;其次支持泛型,我们可以限制在一个集合中只能放入同一种数据类型的元素,例如:

List<String> list = new ArrayList<>(); // 只能放入String类型

        最后,Java访问集合总是通过统一的方式——迭代器(Iterator)来实现,它最明显的好处在于无需知道集合内部元素是按什么方式存储的。
        另外,由于Java的集合设计非常久远,中间经历过大规模改进,我们要注意到有一小部分集合类是遗留类,不应该继续使用:

  • Hashtable:一种线程安全的Map实现;
  • Vector:一种线程安全的List实现;
  • Stack:基于Vector实现的LIFO的栈;

三、List集合

        在集合类中,List是最基础的一种集合:它是一种有序列表。List的行为和数组几乎完全相同:List内部按照放入元素的先后顺序存放,每个元素都可以通过索引确定自己的位置,List的索引和数组一样,从0开始。

List的特点:

  • 元素有序的-即存入顺序和取出顺序是一致的(注意区分有序和排序)
  • 是可以重复的

我们观察List<E>接口,可以看到几个主要的接口方法:

  • 在末尾添加一个元素:boolean add(E e)
  • 在指定索引添加一个元素:boolean add(int index, E e)
  • 删除指定索引的元素:E remove(int index)
  • 删除某个元素:boolean remove(Object e)
  • 获取指定索引的元素:E get(int index)
  • 获取链表大小(包含元素的个数):int size()

1. ArrayList容器类

1.1 常用方法

方法名说明
public boolean add(E e)将指定的参数元素追加到集合的末尾
public void add(int index ,E e)在集合的指定位置添加指定的元素(插入元素)
public void addAll(E object)用于将指定集合中所有元素添加到当前集合中
boolean addAll(int  index,Collection<? extends E> c)  从指定的位置开始,将指定 collection 中的所有元素插入到此列表中
方法名说明
public boolean remove(Object o)删除指定的元素,成功则返回true
public E remove(int index)删除指定索引位置的元素,返回被删除的元素
public E set(int index,E e)修改指定索引位置的元素,返回修改前的元素
public E get(int index)获取指定索引对应的元素
public int size()获取结合中元素个数
1.1.1 增加
  • boolean add(E,e)添加指定元素到集合尾部
    //泛型使用的目的:帮助我们建立类型安全的集合,添加元素的时候传入实际的类型//泛型使用好处: 代码可读性增强,程序更安全//泛型集合--泛型必须是引用数据类型ArrayList<String> arrayList =new ArrayList<String>();//add(元素)添加元素到集合的尾部boolean b = arrayList.add("z张三");System.out.println("添加z张三是否成功:"+b);arrayList.add("l李四");arrayList.add("w王五");arrayList.add("r任六");arrayList.add("z张三");System.out.println(arrayList);运行结果:
    添加z张三是否成功:true
    [z张三, l李四, w王五, r任六, z张三]
  •  void add(int index, E element)添加新元素到集合指定的下标位置
    //add(int index, E element)添加新元素到集合指定的下标位置arrayList.add(0,"孙二娘");arrayList.add(3,"刘备");System.out.println(arrayList);//[孙二娘, z张三, l李四, 刘备, w王五, r任六, z张三]
    
  • boolean addAll(Collection<? extends E> c)  添加集合C 内所有元素到当前集合 
    //使用Arrays.asList方法快速生成一个List集合//Arrays.asList返回的不是java.util下的ArrayListList<String> list = Arrays.asList("李白","高适","李清照","杜甫");//boolean addAll(Collection<? extends E> c)  添加集合C 内所有元素到当前集合arrayList.addAll(list);System.out.println(arrayList);//[孙二娘, z张三, l李四, 刘备, w王五, r任六, z张三, 李白, 高适, 李清照, 杜甫]
  • boolean addAll(int  index,Collection<? extends E> c)  从指定的位置开始,将指定 collection 中的所有元素插入到此列表中
    //boolean addAll(Collection<? extends E> c)  添加集合C 内所有元素到当前集合arrayList.addAll(list);System.out.println(arrayList);//[李白, 高适, 李清照, 杜甫, 孙二娘, z张三, l李四, 刘备, w王五, r任六, z张三, 李白, 高适, 李清照, 杜甫]
    
1.1.2 查找
int  size() 

查集合的长度,具体的元素个数

ArrayList<String> arrayList = new ArrayList<String>();arrayList.addAll(Arrays.asList("李白","高适","李清照","杜甫"));//1.获取元素的个数int size = arrayList.size();System.out.println("元素的个数为:"+size);//元素的个数为:4
E  get(int index) 

获取下标中的元素

//2.E get(int index)获取下标中的元素,System.out.println("首元素:"+arrayList.get(0));//首元素:李白System.out.println("尾元素:"+arrayList.get(arrayList.size()-1));//尾元素:杜甫
int indexOf(Object  c) 

查找找到指定元素的下标位置,如果不存在,则返回数组-1 

//3.int indexOf(Object  c) 查找找到指定元素的下标位置,如果不存在,则返回数组-1int index =arrayList.indexOf("高适1");System.out.println("高适所对应的下标位置:"+index);//高适所对应的下标位置:-1
boolean contains(Object  c)

判断集合中是否存在元素

//4.boolean contains(Object  c)System.out.println("高适是否存在:"+arrayList.contains("高适1"));//高适是否存在:false
boolean  isEmpty()

判断集合是否为空

 //5.判断集合是否为空boolean  isEmpty()System.out.println("集合是否为空:"+arrayList.isEmpty());//集合是否为空:false
List<E>  SubList(int fromindex,int  toIndex)

        subList是List接口中定义的一个方法,该方法主要用于返回一个集合中的一段、可以理解为截取一个集合中的部分元素,他的返回值也是一个List。

		//6.List<E>  SubList(int fromindex,int  toIndex)List<String> subList = arrayList.subList(0, 3);System.out.println(subList);//[李白, 高适, 李清照]
boolean equals(Object o)

  ArrayList.equals(Object obj) 方法比较的是两个列表(ArrayList或其它类型的List)的内容是否相等,即两个列表的大小必须相同,并且在相同索引位置上的元素也必须相等。

    //7.equals()boolean bequals = arrayList.equals(subList);System.out.println(bequals);//false
1.1.3 修改
E set(int index, E element)

修改指定索引位置的元素,返回修改前的元素

ArrayList<String> arrayList = new ArrayList<String>();arrayList.addAll(Arrays.asList("李白", "高适", "李清照", "杜甫"));System.out.println("原集合的内容:" + arrayList);// 修改指定下标的元素String result = arrayList.set(0, "王维");System.out.println("修改的元素:" + result);System.out.println("修改后的集合:" + arrayList);
1.1.4 删除
  • E remove(int index):根据指定索引删除元素,并把删除的元素返回 如果下标超过集合的最大下标,输出IndexOutOfBoundsException
// E remove(int index):根据指定索引删除元素,并把删除的元素返回String oldValue = arrayList.remove(0);System.out.println("删除的下标为0的元素为:" + oldValue);//删除的下标为0的元素为:李白
  • boolean remove(Object o):从集合中删除指定的元素,删除一个就返回 如果查到或者删除1个就返回,并不是删除所有相同的集合元素
//boolean remove(Object o):从集合中删除指定的元素,删除一个就返回boolean b = arrayList.remove("高适");System.out.println("删除元素高适是否成功:" + b);//删除元素高适是否成功:true
  • void clear():删除集合中的所有元素,此集合仍旧存在,集合元素长度变0
		//清空元素arrayList.clear();System.out.println(arrayList.size());//0
 boolean removeAll(Collection<?> c)--- 差集

从集合中删除一个指定的集合元素:
删除A集合中存在B集合中的所有相同的元素,如果有删除返回True

ArrayList<String> list1 = new ArrayList<String>();list1.addAll(Arrays.asList("周杰伦", "郭德刚", "张学友", "于适"));ArrayList<String> list2 = new ArrayList<String>();list2.addAll(Arrays.asList("周杰伦", "王一博", "张学友", "吴磊"));// boolean removeAll(Collection<?> c)--- 差集boolean b = list1.removeAll(list2);System.out.println(b);//trueSystem.out.println(list1);//[郭德刚, 于适]System.out.println(list2);//[周杰伦, 王一博, 张学友, 吴磊]
boolean retainAll(Collection<?> c)   --交集 

保留集合A和集合B中相同的元素,删除不同的元素,谁调用操作的是就是谁

ArrayList<String> list1 = new ArrayList<String>();list1.addAll(Arrays.asList("周杰伦", "郭德刚", "张学友", "于适"));ArrayList<String> list2 = new ArrayList<String>();list2.addAll(Arrays.asList("周杰伦", "王一博", "张学友", "吴磊"));//		boolean retainAll(Collection<?> c)   --交集boolean result=list1.retainAll(list2);System.out.println(result);//trueSystem.out.println(list1);//[周杰伦, 张学友]System.out.println(list2);//[周杰伦, 王一博, 张学友, 吴磊]
1.1.5 其他方法
clone()  

克隆一个集合,得到的一个长度,个数,内容,顺序完全一致的集合,单是赋值了一份

ArrayList<String> list1 = new ArrayList<String>();list1.addAll(Arrays.asList("z周杰伦", "g郭德刚", "d张学友", "y于适"));System.out.println("原集合:" + list1);//原集合:[z周杰伦, g郭德刚, d张学友, y于适]// list.clone() 克隆一个集合,得到的一个长度,个数,内容,顺序完全一致的集合,单是赋值了一份ArrayList<String> cloneList = (ArrayList<String>) list1.clone();System.out.println("克隆的集合:" + cloneList);//克隆的集合:[z周杰伦, g郭德刚, d张学友, y于适]
sort()

对list中的内容进行排序,需要自定义排序规则

// list.sort() 对list中的内容进行排序,需要自定义排序规则list1.sort(new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o1.compareTo(o2);}});System.out.println(list1);//[d张学友, g郭德刚, y于适, z周杰伦]
List和Array转换
  • object[] toArray()直接返回一个Object[]数组:
// object[] toArray()Object[] objects = list1.toArray();System.out.println("objects:"+Arrays.toString(objects));//objects:[d张学友, g郭德刚, y于适, z周杰伦]
  •  T[] toArray(T[] a)传入一个类型相同的Array,List内部自动把元素复制到传入的Array中:
// T[] toArray(T[] a)以较长的长度为String[] arrayList = list1.toArray(new String[0]);System.out.println("arrayList:"+Arrays.toString(arrayList));//arrayList:[d张学友, g郭德刚, y于适, z周杰伦]

1.2 遍历

1.2.1 for循环

和数组类型,我们要遍历一个List,完全可以用for循环根据索引配合get(int)方法遍历:

        

ArrayList<String> arrayList = new ArrayList<String>();arrayList.addAll(Arrays.asList("李白", "高适", "李清照", "杜甫"));// 1.遍历for (int i = 0; i < arrayList.size(); i++) {System.out.print(arrayList.get(i) + " ");}
运行结果:李白 高适 李清照 杜甫 
1.2.2 增强for循环

        只要实现了Iterable接口的集合类都可以直接用for each循环来遍历,Java编译器本身并不知道如何遍历集合对象,但它会自动把for each循环变成Iterator的调用,原因就在于Iterable接口定义了一个Iterator<E> iterator()方法,强迫集合类必须返回一个Iterator实例。

ArrayList<String> arrayList = new ArrayList<String>();arrayList.addAll(Arrays.asList("李白", "高适", "李清照", "杜甫"));// 2.for eachfor (String str : arrayList) {System.out.print(str + "_");}
运行结果:李白_高适_李清照_杜甫_
1.2.3 迭代器

        是访问数据的模型,主要用来遍历Colllection集合。使用迭代器Iterator来访问List。Iterator本身也是一个对象,但它是由List的实例调用iterator()方法的时候创建的。Iterator对象知道如何遍历一个List,并且不同的List类型,返回的Iterator对象实现也是不同的,但总是具有最高的访问效率。

Iterator对象有两个方法:

  • boolean hasNext()判断是否有下一个元素,
  • E next()返回下一个元素。

因此,使用Iterator遍历List代码如下:

// 3.迭代器// 3.1 获取当前集合的“普通的”迭代器对象Iterator<String> it = arrayList.iterator();// 通过迭代器对象判断是否存在下一个元素while(it.hasNext()) {System.out.print(it.next()+" ");//获取下一个元素}System.out.println();运行结果:李白 高适 李清照 杜甫 

使用List迭代器遍历:

//3.2获取当前集合的"List迭代器"//从指定的下标开始正序遍历元素ListIterator<String> listIt = arrayList.listIterator(0);while(listIt.hasNext()) {System.out.print(listIt.next()+" ");//获取下一个元素}System.out.println();//逆序遍历集合ListIterator<String> listIt1 = arrayList.listIterator(4);while(listIt1.hasPrevious()) {System.out.print(listIt1.previous()+" ");}
运行结果:
李白 高适 李清照 杜甫 
杜甫 李清照 高适 李白 
Iterator的remove 
  • ①在使用迭代器的remove()操作时,会将更新后的modCount给expectedModCount,两者会得到同步,但是在调用集合的remove()方法后,两个不会进行同步,进而导致在checkForComodification()校验时不通过,抛出java.util.ConcurrentModificationException异常。
  • ②所以,在单线程下使用迭代器是没有问题的,但是在多线程下同时操作集合就不允许了,可以通过fail-fast快速失败机制,快速判断是否存在同时操作问题。因此,集合在多线程下使用是不安全的。
     Collection c2 = new ArrayList();c2.add("abc");c2.add("def");c2.add("xyz");Iterator it2 = c2.iterator();while(it2.hasNext()){Object o = it2.next();// 删除元素// 删除元素之后,集合的结构发生了变化,应该重新去获取迭代器// 但是,循环下一次的时候并没有重新获取迭代器,所以会出现异常:java.util.ConcurrentModificationException// 出异常根本原因是:集合中元素删除了,但是没有更新迭代器(迭代器不知道集合变化了)//c2.remove(o); // 直接通过集合去删除元素,没有通知迭代器。(导致迭代器的快照和原集合状态不同。)// 使用迭代器来删除可以吗?// 迭代器去删除时,会自动更新迭代器,并且更新集合(删除集合中的元素)。it2.remove(); // 删除的一定是迭代器指向的当前元素。System.out.println(o);}System.out.println(c2.size()); //0
    

1.3 初始化

无参初始化
  • 无参构造初始化:内部数组初始化成空数组
//		1.无参构造初始化:内部数组初始化成空数组ArrayList<String> list1 =new ArrayList<String>();
有参初始化
  • ArrayList(int initialCapacity)初始化成长度为指定容量的Object[]数组
//		2.ArrayList(int initialCapacity)初始化成长度为指定容量的Object[]数组ArrayList<String> list2 =new ArrayList<String>(10);System.out.println(list2.size());//0
  • ArrayList(Collection<? extends E> c) 内部的数组被集合进行初始化
    //		3.ArrayList(Collection<? extends E> c) 内部的数组被集合进行初始化ArrayList<String> list3=new ArrayList<String>(Arrays.asList("abc","def"));System.out.println(list3);//[abc, def]

1.4 底层源码解析(⭐)

List的主要实现类,底层使用Object[]存储,适用于频繁的查找工作,线程不安全。

【特点】 

  • 增删慢:每次删除元素,都需要更改数组长度、拷贝以及移动元素位置;    
  • 查询快:由于数组在内存中是一块连续空间,因此可以根据地址+索引的方式快速获取对应位置上的元素。

【数据结构】 底层是基于数组实现的,随着元素的增加而动态扩容

                        使用场景:适合数据连续性遍历,读多写少的场景


		ArrayList<String> list = new ArrayList<String>(0);//第一次往无参构造的数组list中添加元素的时候,数组首次扩容10list.add("zkt");list.add("zkt");list.add("zkt");list.add("zkt");list.add("zkt");list.add("zkt");list.add("zkt");list.add("zkt");list.add("zkt");list.add("zkt");//...//后面每次容量不足时扩容为容量的1.5倍list.add("张kt");System.out.println(list);//[zkt, zkt, zkt, zkt, zkt, zkt, zkt, zkt, zkt, zkt, 张kt]list.addAll(Arrays.asList("张三","李四","王五"));

底层代码:

属性:

private static final int DEFAULT_CAPACITY = 10;// 默认的初始容量是10
// 空元素数组
private static final Object[] EMPTY_ELEMENTDATA = {};//有参构造所创建
// 默认容量的空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//无参构造所创建的
// 存储元素的数组 
transient Object[] elementData;//底层为Object类型的数组,存储的元素都在此。
// 集合容量
private int size;

  构造方法 :

// 1.构造一个初始容量的空数组。
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}// 2.构造具有指定初始容量的数组。
public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);}
}//3.构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序
public ArrayList(Collection<? extends E> c) {// 将集合构造中的集合对象转成数组Object[] a = c.toArray();if ((size = a.length) != 0) {if (c.getClass() == ArrayList.class) {// 类型为ArrayList则直接赋值elementData = a;} else {//如果不一样,使用Arrays的copyOf方法进行元素的拷贝elementData = Arrays.copyOf(a, size, Object[].class);}} else {// replace with empty array.elementData = EMPTY_ELEMENTDATA;}
}
扩容源码
// 添加一个元素
public boolean add(E e) {ensureCapacityInternal(size + 1);  // Increments modCount!!elementData[size++] = e;//e 操作对象;  elementData 底层操作的数组;size 默认大小0return true; 
}// 1.主体函数
private void ensureCapacityInternal(int minCapacity) {// 对容量进行判断ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}// 2.通过最小容量和默认容量求出较大值 (主要用于第一次扩容:如果是无参构造方式创建的数组对象,第一次添加元素的时候扩容到大小为10)
private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;
}// 3.判断是否需要进行扩容
private void ensureExplicitCapacity(int minCapacity) {// 实际修改集合次数+1 (在扩容的过程中没用,主要是用于迭代器中)modCount++;// 判断当前最小容量是否大于数组长度if (minCapacity - elementData.length > 0)// 将计算出来的容量传递给核心扩容方法grow(minCapacity);
}// 4.核心扩容方法
private void grow(int minCapacity) {// 记录数组的实际长度int oldCapacity = elementData.length;// 核心扩容算法,原容量的1.5倍int newCapacity = oldCapacity + (oldCapacity >> 1);// 判断新容量是否小于当前最小容量(第一次调用add方法必然小于)if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 判断新容量是否大于最大数组长度,如果if (newCapacity - MAX_ARRAY_SIZE > 0)// 条件满足就计算出一个超大容量newCapacity = hugeCapacity(minCapacity);// 调用数组工具类方法,创建一个新数组,将新数组的地址赋值给elementDataelementData = Arrays.copyOf(elementData, newCapacity);
}
  1. 当需要添加元素时,ArrayList会先判断当前容量是否足够,如果不足够,则需要进行扩容操作。
  2. 扩容操作的第一步是调用方法,该方法用于确定扩容后的最小容量。
  3. 如果ArrayList为空,则选择默认容量和传入容量的较大值作为新容量。
  4. 然后调用ensureExplicitCapacity方法,该方法用于判断是否需要进行扩容操作
  5. ensureExplicitCapacity方法中,修改操作次数加1,然后判断如果需要的最小容量大于当前容量,则进行扩容操作。
  6. 扩容操作的第二步是调用grow方法,该方法用于计算新的容量并进行扩容。
  7. 首先获取当前的容量,然后计算新的容量,一般是原容量的1.5倍,并向上取整。
  8. 如果新容量小于所需的最小容量,则直接使用最小容量作为新容量。
  9. 如果新容量超过了最大容量限制,则使用最大容量作为新容量。
  10. 最后,通过调用Arrays.copyOf方法,将原始数组拷贝到新数组中,实现扩容。

总结:

ArrayList扩容的本质就是计算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去。(不是原数组,而是新数组然后给予数组对象地址)。

默认情况下,新的容量会是原容量的1.5倍。 新容量=旧容量右移一位(相当于除于2)在加上旧容量

  ArrayList 的底层是用动态数组来实现的我们初始化一个ArrayList 集合还没有添加元素时,其实它是个空数组,只有当我们添加第一个元素时,内部会调用扩容方法并返回最小容量10,也就是说ArrayList 初始化容量为10。 当前数组长度小于最小容量的长度时(前期容量是10,当添加第11个元素时就就扩容),便开始可以扩容了,ArrayList 扩容的真正计算是在一个grow()里面,新数组大小是旧数组的1.5倍,如果扩容后的新数组大小还是小于最小容量,那新数组的大小就是最小容量的大小,后面会调用一个Arrays.copyof方法,这个方法是真正实现扩容的步骤。

 

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

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

相关文章

运行SpringBoot项目失败?代码出现爆红横线,提示“No beans of ‘UserService‘ type found”让我来看看~

今天在做实验运行项目的时候&#xff0c;发现userService&#xff1a; 一直在提示“No beans of UserService type found”&#xff0c;回去翻了Service业务层的代码&#xff0c;Service注解我也加了呀&#xff0c;奇了怪了。 运行项目&#xff0c;出现了这样的提示&#xff1…

判断一组数据哪些是素数,并统计一个数组中元素的出现频率

import java.util.HashMap; import java.util.Map; public class Test_A26 {//判断一个数是不是素数public static boolean isPrime(int num){if(num<1){return false;}for(int i2;i<Math.sqrt(num);i){if(num%i0){return false;}}return true;}//统计数组中出现的频率 p…

python安装目录文件说明----Dlls文件夹

在Python的安装目录下&#xff0c;通常会有一个DLLs文件夹&#xff0c;它是Python标准库的一部分。这个文件夹包含了一些动态链接库&#xff08;Dynamic Link Libraries&#xff0c;DLL&#xff09;&#xff0c;这些库提供了Python解释器和标准库的一些关键功能。以下是对这个文…

模拟自动滚动并展开所有评论列表以及回复内容(如:抖音、b站等平台)

由于各大视频平台的回复内容排序不都是按照时间顺序&#xff0c;而且想看最新的评论回复讨论内容还需逐个点击展开&#xff0c;真的很蛋疼&#xff0c;尤其是热评很多的情况&#xff0c;还需要多次点击展开&#xff0c;太麻烦&#xff01; 于是写了一个自动化展开所有评论回复…

Kaggle比赛:成人人口收入分类

拿到数据首先查看数据信息和描述 import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # 加载数据&#xff08;保留原路径&#xff0c;但在实际应用中建议使用相对路径或环境变量&#xff09; data pd.read_csv(r"C:\Users\11794\Desk…

嵌入式技术学习——c51——串口

一、串口介绍。 串口是一个 通讯接口。成本低&#xff0c;容易使用&#xff0c;通信线路简单&#xff0c;可实现两个设备的相互通信 单片机的串口可以实现单片机于单片机&#xff0c;单片机与电脑&#xff0c;单片机与其他模块相互通信。 51单片机内部自带UART&#xff0c;通…

Flutter图像编辑器应用:创造生动美丽的照片体验

介绍 引言 想象一下&#xff0c;在一个阳光明媚的下午&#xff0c;与家人或朋友漫步在风景如画的街道上。拿出手机&#xff0c;迫不及待地捕捉这一刻的美好&#xff0c;按下快门&#xff0c;留下了一张充满回忆的照片。 然而&#xff0c;回到家后发现照片的亮度有些偏暗&…

【完结】无代码网页爬虫软件——八爪鱼采集器入门基础教程

《八爪鱼采集器入门基础教程》大纲如下&#xff1a; 课程所提软件&#xff0c;八爪鱼采集器下载&#xff1a; 1.软件分享[耶]八爪鱼&#xff0c;爬取了几百条网站上的公开数据&#xff0c;不用学代码真的很方便。[得意]2.发现了一个很棒的软件&#xff0c;?不用学python也可…

周跳的探测及修复

前言&#xff1a; 本章节代码均在Gitee中开源&#xff1a; 导航工程: 导航工程及其有关的所有项目 - Gitee.comhttps://gitee.com/Ehundred/navigation-engineering/tree/master/%E5%8D%AB%E6%98%9F%E5%AF%BC%E8%88%AA%E5%8E%9F%E7%90%86/%E5%91%A8%E8%B7%B3%E6%8E%A2%E6%B5%…

什么是Vue开发技术

概述 Vue.js 是一个用于构建用户界面的渐进式框架&#xff0c;它设计得非常灵活&#xff0c;可以轻松地被集成到任何项目中。 vue是视图的发音&#xff0c;其目的是帮助开发者易于上手&#xff0c;提供强大的功能构建复杂的应用程序 示例 以下是vue基本的语法概述 声明式渲…

探索未来工作新伙伴:机器人流程自动化(RPA)揭秘

想象一下&#xff0c;如果你的日常工作中那些繁琐、重复的任务&#xff0c;比如数据录入、文件整理、邮件发送等&#xff0c;都能自动完成&#xff0c;你将拥有更多时间专注于真正需要创造力和智慧的工作&#xff0c;是不是听起来就像拥有了一个私人助理&#xff1f;这并不是遥…

VUE3版本新特性

VUE3版本新特性 VUE3和VUE2的区别路由的使用vite安装项目新特性使用 1.VUE3和VUE2的区别 2020年9月18日&#xff0c;Vue.js发布版3.0版本&#xff0c;代号&#xff1a;One Piece 于 2022 年 2 月 7 日星期一成为新的默认版本! Vue3性能更高,初次渲染快55%, 更新渲染快133% 。…

推荐 3 款小巧的文件压缩、投屏和快速启动软件,请收藏,避免找不到

Maya Maya是一款由博主25H开发的体积小巧、简单易用的快速启动工具。它的操作逻辑和界面设计几乎复刻了Rolan早期版本&#xff0c;功能上与Rolan几乎别无二致。Maya支持多文件拖拽添加启动、快捷键呼出、自动多列显示等功能。此外&#xff0c;Maya还具备lnk文件解析功能。 May…

多目标粒子群算法(MOPSO):原理讲解与代码实现 Matlab代码免费获取

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 粒子群算法 多目标粒子群算法 一、外部档案…

Android11 以Window的视角来看FallbackHome的启动

在WMS中&#xff0c;使用WindowState代表着一个Window并维护着一个Window的"层级树"&#xff0c;每个Window需要按照"层级"的规则进行排列。对于FallbackHome&#xff0c;其Window是挂载在home task上&#xff0c;而home task挂载在DefaultTaskDisplayArea…

python之日志(三)--将捕获的异常写入日志中

1.日志级别 import logging #日志模块 #默认下只会从第3级开始打印 logging.debug(DEBUG级别) #1级 logging.info(INFO级别) #2级 logging.warning(WARNING级别) #3级 logging.error(ERROR级别) #4级 logging.critical(CRITICAL级别) #5级 默认第1和第2级的日志不会打印 …

解决 uniapp h5 页面在私有企微iOS平台 间歇性调用uni api不成功问题(uni.previewImage为例)。

demo <template><view class"content"><image class"logo" src"/static/logo.png"></image><button click"previewImage">预览图片</button></view> </template><script> //打…

React@16.x(32)useDebugValue

目录 1&#xff0c;介绍2&#xff0c;作用 1&#xff0c;介绍 从一个例子开始&#xff1a; export default function App() {const [n, setN] useState(0);const refH1 useRef();useEffect(() > {console.log("父组件");});return <h1 ref{refH1}>{n}&l…

使用 imu_utils 、Kalibr 工具进行IMU和相机内外参外参标定

文章目录 一、问题描述二、imu_utils 工具的使用1. 安装1.1 下载与编译1.2 编译bug解决 2. 标定 IMU2.1 imu bag包录制2.1.1 imu 数据格式2.1.2 imu 数据录制 2.2 imu 标定 三、Kalibr 工具的使用1. 安装1.1 下载与编译1.2 问题解决 一、问题描述 vins系列安装完成后&#xff…

EasyRecovery电脑数据恢复软件2024数据守护神#误删文件神器#硬盘恢复利器#数据丢失救星

&#x1f310; 你是否曾经因为误删文件、硬盘损坏等原因&#xff0c;失去了重要的数据&#xff1f;别担心&#xff0c;EasyRecovery电脑数据恢复软件是你的救星&#xff01;它能够帮你找回丢失的文件&#xff0c;让你的数据重新焕发生机。 &#x1f50d; EasyRecovery软件的核…