java第十五讲集合概括(详谈ArrayList,LinkedList)

java中的常量

1、对于java中的常量名称规则:所有的单词字母都是大写,如果有多个字母,那么使用下划线连接。

2、在java中声明final常量的时候通常都会加上static关键字,这样对象的每个实例都会访问唯一的一份常量值。
原因是因为:如果不加static直接使用final修饰的话,每个对象里面的值都会有这个常量,这个常量是不能改变的。如果加了static,则所有对象共享这个常量,这个常量也是不能改变的,加上static更好维护。

IDE

IDE(Integrated Development Environment),集成开发环境。
比如Eclipse、Intellij IDEA等等

集合

3、 集合:集合是整个java中最重要的一部分,集合是建立在数组之上以及对后面开发有很大影响。

一、标题ArrayList(数组列表)

标题ArrayList底层是用数组实现的存储

(1)、ArrayList的特点

查询效率高,删除效率低,线程不安全,使用频率高。

(2)、ArrayList的六大问题

1、查询效率高?

ArrayList是顺序结构,只要知道存储的首地址以及各个大数据元素所占单元,就可以计算出各元素的存储地址。

2、删除效率低?

取决于你要删除的元素离数组末端有多远,ArrayList拿来做堆栈来用还是挺合适的,push和pop操作不涉及数据移动操作。。

3、线程不安全?

当然是不安全的,线程安全的版本的数组容器为Vector,Vector的实现很简单,就是把所有的方法就加上synchronized。

4、为什么线程不安全,它使用频率还高?

因为在我们正常使用场景中,一般都是查询,很少有频繁的增删,如果涉及频繁的增删,可以使用LinkedList。

5、ArrayList如何扩容?

ArrayList的默认大小为10(没找到什么具体原因,估计长度为10最常用,最有效率)。ArrayList可以通过构造方法在初始化的时候指定底层数组的大小。
在这里插入图片描述
源码中可以看出通过无参构造方法初始化ArrayList(),则赋值为一个默认空的数组,所有容量为0,只有真正对数据进行add时,才分配默认的大小为10.数组的长度有限制,ArrayList可以存放任意数量对象,通过数组扩容,扩容后的大小 等于扩容前大小的1.5倍。 把原数组的数据原封不动的复制到新数组。
在这里插入图片描述

/** * 要分配的最大数组大小 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 
/** * ArrayList扩容的核心方法。 */
private void grow(int minCapacity) {
	// oldCapacity为旧容量,newCapacity为新容量
	int oldCapacity = elementData.length; 
	//将oldCapacity 右移一位,其效果相当于oldCapacity /2,
	//我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍,
	int newCapacity = oldCapacity + (oldCapacity >> 1); 
	//然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量,
	if (newCapacity - minCapacity < 0) 
		newCapacity = minCapacity; 
	// 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) `hugeCapacity()` 方法来比较 minCapacity 和 MAX_ARRAY_SIZE,
	//如果minCapacity大于最大容量,则新容量则为`Integer.MAX_VALUE`,否则,新容量大小则为 MAX_ARRAY_SIZE 即为 `Integer.MAX_VALUE - 8`。
	if (newCapacity - MAX_ARRAY_SIZE > 0) 
		newCapacity = hugeCapacity(minCapacity); 
	// minCapacity is usually close to size, so this is a win: 
	elementData = Arrays.copyOf(elementData, newCapacity); 
	}
将oldCapacity 右移一位,其效果相当于oldCapacity /2,我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍, int newCapacity = oldCapacity + (oldCapacity >> 1);

看System.arraycopy方法将原数组的内容拷贝到扩容的新数组中:

import java.util.Arrays;
/**
 * 
 * @author xinbai 
 *  2020-4-17,下午8:46:54
 */
public class Demo3ArrayList {

	public static void main(String[] args) {
		int [] arr={1,2,3};	
	int [] brr=new int[10];
	System.arraycopy(arr, 0, brr, 0, arr.length);
	System.out.println(Arrays.toString(brr));
			}
}

在这里插入图片描述
Arrays.copyof()方法给原数组扩容:

import java.util.Arrays;
/**
 * 
 * @author xinbai 
 *  2020-4-17,下午8:46:54
 */
public class Demo3ArrayList {

	public static void main(String[] args) {
		int [] arr={1,2,3};	
	int [] brr=Arrays.copyOf(arr, 10);
	System.out.println(brr.length);
	System.out.println(Arrays.toString(brr));
			}
}

在这里插入图片描述

6、数组用来做队列合适吗?

队列一般是FIFO的,如果用ArrayList做队列,就需要在数组尾部追加数据,数组头部删除数组,反过来也可以。但是无论如何总会有一个操作会涉及到数组的数据搬迁,这个是比较耗费性能的。这个回答是错误的!ArrayList固然不适合做队列,但是数组是非常合适的。

二、LinkedList

LinkedList是基于双向列表来实现,利于插入,删除,仅需修改数据元素的指针字段值,而不必移动数据元素。
LinkedList的时间复杂度为O(N),ArrayList不考虑底层数组自动扩容的话,时间复杂度为O(1),在指定位置添加元素,根据最坏打算,时间复杂度是O(n)。

LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。

ArrayList适合查找,LinkedList适合增删。

三、List

集合中的List这个接口主要由两个实现类,一个是实现类是ArrayList[数组列表],另外一个LinkedList实现类[链接列表或者交列表],这两个类都实现了List的这个接口,所以它们的方法有很多共通的地方。

猜你喜欢

转载自blog.csdn.net/qq_44830627/article/details/105465212