Collection接口子接口之一:List接口
面试题:ArrayList,linkedList,Vector三者异同
同:三个类都是实现了List接口,存储数据特点相同:存储有序的,可重复的数据
不同:ArrayList:作为List接口的主要实现类,线程不安全的,效率高,底层使用Object[] elementData存储
linkedList:对于频繁的插入,删除操作,使用此类效率比ArrayList高,底层使用双向链表存储
Vector:作为List接口的古老实现类,线程安全的,效率低,底层使用Object[] elementData存储
ArrayList源码分析:jdk 7 情况下
ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中
结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)
jdk 8 的变化:
ArrayList list = new ArrayList();//底层Object[] elementData初始化为{},并没有创建长度为10的数组
list.add(123);//第一次调用add时,底层才创建了长度为10的数组
linked源码分析:
linkedList list = new linkedList();内部声明了Node类型的first和last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node对象
Vector源码分析:jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组,在扩容方面,默认扩容为原来数组的长度的2倍
总结常用方法
增:add(Object obj)
删:remove(int index)/ remove(Object obj)
改:set(int index,Object ele)
查:get(int index)
插:add(int index,Object ele)
长度:size()
遍历:1.Iterator迭代器方式
2.增强for循环
3.普通循环
Set接口:存储无序的,不可重复的数据
hashset:作为set接口的主要实现类,线程不安全,可以存储null值
linkedhashset:作为hashset的子类,遍历器内部数据时,可以按照添加的顺序遍历
treeset:可以按照添加对象的指定属性,进行排序
以hashset为例说明:
1.无序性:不等于随机性,存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的
2.不可重复性:保证添加的元素按照equals()判断时,不能返回true,即:相同的元素只能添加一个
添加元素的过程:我们向hashset中添加元素a,首先调用元素a所在类的hashcode()方法,计算元素a的哈希值,此哈希值接着通过某种算法计算出在hashset底层数组中的存放位置(即索引位置),判断数组此位置上是否已经有元素
如果此位之上没有其他元素,则a添加成功--->情况一
如果此位之上有其他元素b(或以链表形式存在的多个元素),则比较a与b的哈希值:
如果哈希值不同则a添加成功--->情况二
如果哈希值相同,进而调用equals()方法:
返回true,a添加失败
返回false,a添加成功--->情况三
对于添加成功的情况二和三来说,元素a与存在指定索引位置上数据以链表的方式存储
jdk8中,原来的元素在数组中指向元素a
hashset底层:数组+链表的结构
1.set接口中没有额外定义新的方法,使用的都是collection中声明过的方法
2.要求:向set中添加的数据,其所在的类一定要重写hashcode()和equals()
要求:重写的hashcode()和equals()尽可能保持一致性,相等的对象必须具有相等的散列码
1.向treeset中添加的数据,要求是相同类的对象
2.两种排序方式:自然排序(实现comparable接口)和定制排序(comparator)
自然排序中:比较两个对象是否相同的标准为:compareTo()返回0,不再是equals()
定制排序:比较两个对象是否相同的标准为:compare()返回0,不再是equals()
面试题:在list内去除重复数字值,要求尽量简单
List list = new ArrayList();
Hash Set = new HashSet();
set.addAll(list);//set不允许存储重复数据
return new ArrayList(set);
Map接口:双列数据,存储key-value对的数据
HashMap:作为map的主要实现类,线程不安全的,效率高,存储null的key和value
linkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历
原因:在原有的hashmap底层结构基础上,添加了一对指针,指向前一个和后一个元素
TreeMap:保证按照添加的key-value对进行排序,实现遍历排序此时考虑key的自然排序和定制排序
底层使用红黑树
Hashtable:作为古老的实现类,线程安全的,效率低,不能存储null的key和value
properties:常用来处理配置文件,key和value都是string类型
hashmap底层:数组+链表+红黑树(jdk 8)
map结构的理解:
map中的key:无序的,不可重复的,使用set存储所有的key--->key所在的类要重写equals()和hashcode()(以hashmap为例)
map中的value:无序的,可重复的,使用collection存储所有的value(要重写equals())
一个键值对:key-value构成了一个Entry对象
map中的entry:无序的,不可重复的,使用set存储所有的entry
1.new HashMap():底层没有创建一个长度为16的数组
2.底层数组为Node[]
3.首次调用put()方法时,底层创建长度为16的数组
4.当数组的某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组的长度>64时,此时此索引位置上的所有数据改为使用红黑树存储
map常用方法:添加删除修改操作:
Object put(Object key,Object value):将指定key-value添加或修改到当前map对象中
void putAll(Map m):将m中所有key-value对存放到当前map中
Object remove(Object key):移除指定key的key-value对,并返回value
void clear():清空当前map中所有数据//与map=null不同,此时map={}
元素查询操作:
Object get(Object key):获取指定key对应的value
boolean containsKey(Object key):是否包含指定key
boolean containsValue(Object value):是否包含指定value
int size():返回map中key-value对的个数
boolean isEmpty():是否为空
boolean equals(Object obj):判断当前map和参数对象obj是否相等
遍历所有的key集:keyset():Set set = mep.keySet();再使用迭代器
遍历所有的value集:values():Collection values = map.values();
遍历所有的key-value:entrySet():Set entrySet = map.entrySet();再使用迭代器,entrySet集合中的元素都是entry,再使用强转Map.Entry entry = (Map.Entry) obj;再使用getKey()或getValue()获取
向treemap中添加key-value,要求key必须是由同一个类创建的对象,因为要按照key进行排序:自然排序,定制排序
Collections:操作Collection,Map的工具类(见笔记)
泛型:把元素的类型设计成一个参数,这个参数类型叫做泛型
所谓泛型,就是允许在定义类,接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型,这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量,创建对象时)确定(即传入实际的类型参数,也称为类型实参)



