Java集合加源码分析

引入

  1. 集合、数组都是可以存储多个数据的结构,简称为Java容器
  2. 数组存储数据的特点:
    1. 一旦数组初始化后,数组的长度就确定了
    2. 数组一旦定义好,可存放元素的数据类型也就确定了
  3. 数组存储数据的缺点:
    1. 长度不可变
    2. 数组中提供的方法有限,对于添加、删除等操作不方便,同时效率也不高
    3. 获取数组中有效元素个数比较困难
    4. 对于无序、不重复的需求无法满足

一、Java集合框架

Collection接口:单列集合,存储一个一个的对象

​ List接口:有序的、可重复的数据(可理解为动态数组)

​ ArrayList、LinkedHashSet、Vector

​ Set接口:无序的、不可重复的数据(可理解为高中数学中的集合)

​ HashSet、LinkedHashSet、TreeSet

Map接口:双列集合,存储一对(key—value)一对的数据(可理解为函数)

​ HashMap、LinkedHashMap、TreeMap、HashTable、Properties

二、Collection接口方法

查看 Collection 接口可知有 15 个抽象方法,供实现类实现,下面详解其中 13 个


1 boolean add(E e)	向集合中添加元素,只能添加引用类型,不能添加基本类型
    
2 boolean addAll(Collection c)	将形参集合的元素添加到当前集合
    
3 void clear()	删除当前集合所有元素
    
4 boolean comtains(Object obj)	会调用obj对象所在类的equals方法,判断形参传入集合中的值是否在当前集合内
    
5 boolean contains(Collection coll)	判断形参coll的元素是否都在当前集合内
    
6 boolean equals(Object o)	判断当前集合和形参集合元素是否相等
    
7 int hashCode()	返回当前集合的hashCode值
    
8 boolean isEmpty()		判断当前集合是否为空
   
9 boolean remove(Object obj)		从当前集合删除obj元素
    
10 boolean removeAll(Collection coll)	从当前集合删除coll集合的所有元素
    
11 boolean retainAll(Collection coll) 	求两个集合的交集,并返回给当前集合
    
12 int size()		返回当前集合的长度
    
13 Object[] toArray() 		将当前集合转换为数组

三、Iterator迭代器接口

Iterator对象称为迭代器,主要用于遍历Collection集合中的元素、同时也可以在遍历时删除集合中的元素

Iterator 仅适用于集合遍历

集合对象每次调用 iterator()方法都会得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前

Collection coll = new ArrayList();
Iterator iterator = coll.iterator();

//遍历集合
while(iterator.hasNext()){
    
    
    iterator.next();
}

hasNext()   判断是否还有下一个元素
next()   指针下移、下移后将集合位置上的元素返回

四、Collection子接口一:List

List 接口常用的实现类有:ArrayList LinkedList Vector

异同点:

​ 同:三个类都实现了List接口

ArrayList 作为List的主要实现类、线程不安全、效率高、底层使用Object[]存储
LinkedList 底层使用双向链表存储、频繁添加、删除的效率高
Vector 作为List的古老实现类、线程安全、效率低、底层使用Object[]存储

List接口的常用方法

void add(int index,Object ele)	在index位置插入ele元素

boolean addAll(int index,Collection eles)	从index位置开始将eles中的所有元素添加进来
    
Object get(int index)	获取index位置的元素
    
int indexOf(Object obj)		返回obj第一次出现的索引
    
int lastIndexOf(Object obj)		返回obj在当前集合最后一次出现的索引
    
Object remove(int index)	移除index位置的元素,并返回该元素
    
Object set(int index,Object obj)	设置index位置的元素为obj
    
list subList(int fromIndex,int toIndex)		返回从fromIndex到toIndex的子集合	

List的遍历(三种方式)

ArrayList list = new ArrayList();
list.add(123);
list.add("asd");

//方式一:Iterator方式
Iterator iterator = list.iterator();
while(iterator.hasNext()){
    
    
    iterator.next();
}
//方式二:增强for循环
for(Object obj : list){
    
    
    System.out.println(obj);
}
//方式三:普通for循环
for(int i = 0; i < list.size ; i++){
    
    
    System.out.println(list.get(i));
}

ArrayList源码分析:

ArrayList arr = new ArrayList();	//底层创建长度为10的Object[]数组

arr.add(123);	//elementDate[0] = 123
...
arr.add(11);	
//如果此次添加元素导致底层elementDate数组容量不够,则扩容,默认情况下扩容为原来的1.5倍,同时将原数组的元素复制到新数组中
int newCapacity = oldCapacity + (oldCapacity >> 1);
elementData = Arrays.copyOf(elementData, newCapacity);

ArrayList arr = new ArrayList();//底层并没有创建长度为10的数组
arr.add(123);	//第一次调用add方法时,才创建长度为10的数组
后续和7之前一样
    
总结:
    7类似于饿汉式、8类似于懒汉式,节省内存

五、Collection子接口二:Set

Set接口是Collection接口的子接口,没有提供额外的方法,使用的都是Collection声明过的方法

Set集合不允许包含相同的元素

1、Set的理解

1.1、无序性

存储的元素在底层并非按照数组索引的顺序添加,而是根据数组的hash值确定的

1.2、不可重复性

1.3、向set中添加元素的过程

步骤一:向hashSet中添加元素a,首先调用a所在类的hashCode方法,计算hash值,进而通过此hash值通过某种算法计算出该元素在数组中存放的索引值。

步骤二:获得索引值后,判断该位置是否有元素,如果此位置没有元素,则添加成功

​ 如果此位置有元素,,首先比较a和这个位置元素的hash值

​ 如果hash值不同,则元素a添加成功

步骤三: 如果hash值相同,则调用a所在类的equals方法,将其他元素传入equals方法的形参

​ 如果方法返回true,元素a添加失败

​ 如果方法返回false,则添加成功(以链表形式存储)

2、treeSet

一、向treeSet中添加的元素必须是同一个类的对象(这样才能比较大小)

二、两种排序方式

​ 自然排序(实现Comparable接口)

​ 比较两个对象相同的标准不再是equals,而是compareTo方法返回0

​ 定制排序

​ 比较两个对象是否相等的标准不在是equals,而是

六、Map接口

1、Map接口的框架结构

|------Map:存储Key—value对的数据

​ |------HashMap:作为Map的主要实现类;线程不安全;效率高

​ |------LinkedHashMap

​ |------TreeMap:可以进行排序(按照key排序)

​ |------Hashtable:作为Map古老的实现类;线程安全;效率低

​ |------Properties:常用来处理配置文件;键值对都是String类型

HashMap的底层实现原理?

2、key-value的理解

① Map中的key: 无序的,不可重复(用set存储) 所在类要重写equals方法和hashCode方法(针对于HashMap)

② Map中的value:无序的,可重复(用Collection存储) 所在类要重写equals方法(针对于HashMap)

③ 一个键值对构成一个Entry对象(用set存储)

​ put放入的键值对其实是存放到Entry对象中,Entry有两个属性key和value

​ Entry是无序的,不可重复的

3、HashMap的底层实现原理

以JDK7说明
    
HashMap map = new HashMap();	实例化以后,底层创建了长度为16的数组Entry[] table
map.put(key,value);		
首先调用key所在类的hashCode方法,计算key的哈希值,此哈希值经过某种算法计算后,得到key在Entry[]中的存放位置
如果此位置数据为空,则键值对添加成功
    如果此位置数据不为空(意味着此位置存放一个或多个数据(链表存储)),比较当前key和这些数据的哈希值,
    	如果key的哈希值与已经存在的数据局哈希值都不相同,则键值对添加成功
    	如果key的哈希值与已经存在的某个key的哈希值相同,则调用key所在类的equal方法
    		返回true,用value去替换已经存在key的value值
    		返回false,则键值对添加成功
默认扩容方式为原来的2倍,并且赋值过来
    
87的不同点
    1new时,底层并没有创建长度为16的数组
    2 jdk8底层的数组是 Node[],而非Entry[]
    3 首次调用put方法时,底层创建长度为16的数组
    4 JDK8底层使用 数组+链表+红黑树(当数组的某个索引位置上以链表形式存在的数据个数>8且当前数组长度>64,此时索引位置上的所有数据改为使用红黑树存储)

4、Map接口中常用方法

V put(K key,V value)	向map中添加数据
  
V remove(Object key)	通过指定key移除键值对
    
void clear()	清空map集合
    
Object get(Object key)		通过key获取指定value
    
Boolean containsKey(Object key)		是否包含指定的key
    
Boolean containsValue(Object value)		是否包含指定的value
    
int size() 		返回map键值对的个数
    
Boolean isEmpty()	判断map是否为空
    
Boolean equals(Object obj)	判断两个map是否相等

5、Map的遍历

        //遍历所有key
        Set keySet = map.keySet();
        Iterator iterator = keySet.iterator();
        while(iterator.hasNext()){
    
    
            System.out.println(iterator.next());
        }

        //遍历所有value
        Collection values = map.values();
        Iterator iterator1 = values.iterator();
        while(iterator1.hasNext()){
    
    
            System.out.println(iterator1.next());
        }

        //遍历所有键值对
        Set set = map.entrySet();
        for (Object o : set){
    
    
            Map.Entry entry = (Map.Entry) o;
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }

七、Collection工具类

Collections 是一个可以操作Set、List、Map的工具类

reverse(List)	反转List中元素的顺序
    
shuffle(List)	对List集合中的元素进行随机排序
    
sort(List)		根据元素的自然排序对List集合元素进行升序排序
    
sort(List,Comparator)	根据指定的Comparator产生的顺序对List进行排序
    
swap(List,int,int)		将指定List集合中的i处元素和j处元素进行交换
    
int frequency(Collection Object)	返回指定元素出现的次数
    
void copy(List dest,List src)		将原集合复制带目标集合

猜你喜欢

转载自blog.csdn.net/weixin_45321793/article/details/110096891