今天的内容
1.ArrayList【重点】
2.LinkedList【开发不用,但是面试会问】
3.Object【所有的超类】
4.Set接口
1.ArrayList
首先看官方API
Collection下面有一个子接口叫List
List接口下面有一个实现类叫ArrayList
ArrayList底层是数组
ArrayList也是容器,可以放数据
源码分析
/**
* Default initial capacity.
默认的变量,变量值是10 默认的初始化的容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
声明了一个空的数组EMPTY_ELEMENTDATA 变量
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
默认容量的空数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
数组的有效的容量 size 默认值是0
*/
private int size;
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
构造方法,在实例化的时候调用有参数的构造
*/
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);
}
}
/**
* Constructs an empty list with an initial capacity of ten.
无参数的构造方法
构造了一个初始化容量为10的空的数组
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//扩容的方法。当数组的容量不够的话,会自动扩容
private void grow(int minCapacity) {
// overflow-conscious code
//oldCapacity 是老的容量
int oldCapacity = elementData.length;//10个容量 数组里面只能放10个元素
//newCapacity新的容量 (oldCapacity >> 1);叫位元算符
// int newCapacity = oldCapacity + oldCapacity * 0.5;
//int newCapacity = 1.5 * oldCapacity;//扩容的是原来数组的1.5倍
//原来的数据是10 扩容以后的容量是15
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//扩容完以后,进行数组的赋值
//[1,2,3,4,5,6,7,8,9,10] 原来的数组
//[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] 在赋值一个数组这个数组容量是15
//进行数组的扩容了,新的数组还有有老数组中的数据
//所以使用copy方法
elementData = Arrays.copyOf(elementData, newCapacity);
}
面试题:
ArrayList处理数据的特征:
增数据删数据比较慢。为什么?
增加数据效率低:
1.有可能会涉及到数组的扩容,涉及到数组的copy
2.添加数据到指定位置的时候,会导致从添加数据位置开始整体后移
删除数据效率低:
从删除数据开始,数据整体前移一位
查找快。为什么?
用的索引进行查找的
好比一本书,有目录。你要找某一章节,这个章节有页码数,直接翻到页码数
页码数就是这个索引
cpu是通过访问内存地址(数组+下标)直接定位到集合中的元素的
就好比我找咱们的学员,直接通过名字进行查找。所以效率比较高
开发中一般使用ArrayList,开发中查询偏多
查找是1,增删是n,对于ArrayList来说
2.LinkedList
父接口是List
它和ArrayList是亲兄弟。但是开发中使用ArrrayList而不用LinkedList
双向链表:自行车的车链子
LinkedList是队列
队列:先进先出
栈:先进后出 有底的
面试经常问
ArrayList和LinkedList的特点和区别
ArrayList和LinkedList 都是List接口的实现类
ArrayList在查询数据的时候比较快,但是增删慢
LinkedList查询的时候慢,增删的时候快
linkedList底层是双向链表结构
查找慢:是因为使用了二分法查找的算法
[1,2,3,4,5,6,7,8,9,10] 比如找3这个数,
[1,2,3,4,5] [6,7,8,9,10] 一分为2
[1,2,3,4,5] 再一分为2
[1,2,3] [4,5]
[1,2,3] 再一分为2
[1,2] [3] 哦找到了 3
查询的时候进行了n次 使用LinkedList查找的时候进行了n次,他不是一次就出来了
增删快:因为LinkedList底层是一个节点内部类。
开发中咱们只使用ArrayList,而不用LinkedList。因为咱们以后的网站查询使用的较多。增删较少,使用ArrayList的时候几乎不影响效率的
上午讲的东西和开发无关,和面试有关,没有听懂的没有关系,学到后期咱们会专门对源码进行分析,因为你现在 的水平还达不到看源码的程度。
3.Object类
Object类是所有类的基类
toString();
equals();
Object类下面的equals方法比较的是两个对象的地址,比较严格
public boolean equals(Object obj) {
return (this == obj);
}
==比较的是内存地址和内容,比较严格String类下面的equals比较的是内容。充分说明了一点。String类肯定重写了Object
下面的equals方法。
public boolean equals(Object anObject) {
//也是先看两个地址是否一致,如果两个对象的地址一致,肯定内容也一致了
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
//强转 "好像睡觉" = value
// "好像睡觉" = anotherString.value
String anotherString = (String)anObject;
int n = value.length;//字符串的长度 9
if (n == anotherString.value.length) {
//为什么要先比较两个字符串的长度呢?
//比较两个字符串的时候,如果长度不同,这个两个字符串肯定不相等
//如果两个字符串长度相等的话,紧接着比较字符串的内容
char v1[] = value;//[好,像,睡,觉]
char v2[] = anotherString.value;//[好,像,睡,觉]
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
//如果这两个字符串字符数组通过循环挨个比较。如果有一个字符不相等,就返回的是false
return false;
i++;
}
//内容一致的话也是一个true
return true;
}
}
return false;
}int hashCode();
hashCode方法获取的是对象的hash值,也被散列码,实际上是一个十进制int类型的数值
这个值就是对象的内存地址(十六进制的)转为10进制的数据 官方手册:
如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
面试题:
为什么重写了equals方法的时候,必须重写hashCode方法?
两个对象使用equals方法进行比较的时候,如果对象一样的话,hash码可能不一样
咱们要保证你的hash码也必须是一样的。
hash码一样对象肯定一样的
4.Set集合
Set父接口是Collection
Set和List是亲兄弟
List集合的特征是:有序的,可以重复的
Set特征是:无序的,不可重复的
Set接口下面有两个实现类:
HashSet TreeSet
Set接口中没有独特的方法,就是Collection接口下面的方法
Set在开发中用的也比较少