java集合包含ArrayList、Vector源码分析(随堂笔记)

一、集合框架的概述

  1. 集合、数组都是对多个数组进行存储的结构,简称Java容器;

说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储;

  1. 数组在存储多个数据方面的特点:
  • 一旦初始化以后,其长度就确定了;
  • 数组一旦定义好,其元素的类型也就确定了,我们也就只能操作指定类型的数据了;
  1. 数组在存储多个数据方面的缺点:
  • 一旦初始化以后,其长度就不可修改;
  • 数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高;
  • 获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用;
  • 数组存储数据的特点:有序、可重复,对于无序、不可重复的需求,则不能满足;

Java集合可分为Collection和Map两种体系

Collection接口:单列数据,定义了存取一组对象的方法的集合;

  • List:元素有序、可重复的集合;---->“动态”数组

ArrayList、LinkedList、Vector;

  • Set:元素无序、不可重复的集合;

HashSet、LinkedHashSet、TreeSet;

Map接口:双列数据,保存具有映射关系"key-value对"的集合;

  • HashMap、LinkedHashMap、TreeMap、Hashtable、Properties;
Collection接口中声明的方法的测试
  • 向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals()。
public void test(){
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new String("Tom"));
    coll.add(new Person(Jerry,20));
    coll.add(false);
    
    //1.contains(Object obj):判断当前集合中是否包含obj;
    //我们在判断时会调用obj对象所在类的equals();
    
    boolean contains = coll.contains(123);
    System.out.println(contains);//true
    
    System.out.println(coll.contains(new String("Tom")));//true
    
    System.out.println(coll.contains(new Preson(Jerry,20)));//Preson方法重写了就是true,否则就是false
    
    //2.CollectionsAll(Collections coll1):判断形参coll1中的所有元素是否都存在于当前集合中;
    Collection coll1 = Arrays.asList(123,456);
    System.out.println(coll.containsAll(coll1));//true
    
    //3.remove(Object obj):从当前集合中移除obj元素;
    //4.removeAll(Collection coll):从当前集合中移除coll中所有的元素;
}
集合元素的遍历操作,使用迭代器Iterator接口
//内部的方法:hasNext()和 next

//hasNext()判断是否还有下一个元素
while( iterator.hasNext() ){
    //next() 指针下移、将下移以后集合的位置上的元素返回
    System.oout.println( iterator.next( ) );
}    
  1. 集合对象每次调用iterator()方法都得到一个全新的迭代对象,默认游标都在集合的第一个元素之前;
  2. 内部定义了remove(),可以在遍历的时候,删除集合中的元素,此方法不同于集合直接调用remove();

for(集合元素的类型 局部变量 :集合对象),其内部仍然调用了迭代器;

ArrayList、LinkedList、Vector三者的异同?

  • 相同点:三个类都实现了List接口,存储数据的特点相同:存储有序的、可重复的数据;
  • 不同点

ArrayList:作为List接口的主要实现类:执行效率高,但线程不安全;底层使用Object[ ] elementData存储

LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高,底层使用的是双向链表存储;

Vector:作为List接口的古老实现类:执行效率低,但线程安全;底层使用Object[ ] elementData存储;

ArrayList的源码分析

jdk 7 情况下

ArrayList list = new ArrayList();//底层创建了长度是10的Object[ ]数组elementData

list.add(123);//elementData[0] = new Integer(123)

list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。

默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中;

结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(iint capacity)

jdk 8中ArrayList的变化

ArrayList list = new ArrayList();//底层Object[ ] elementData初始化为{ },并没有创建长度为10的数组;

list.add(123);//第一次调用add()时,底层才创建长度为10的数组,并将数据123添加到elementData[0]

后续的添加和扩容操作与jdk 7 无异;

Vector源码分析
  • jdk 7 和 jdk 8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组;
  • 在扩容方面,默认扩容为原来数组长度的2倍;
List的常用方法
  • void add (int index , Object ele):在index位置插入ele元素;
  • boolean addALL(int index , Collection eles):从index位置开始将eles中的所有元素添加进来;
  • Object get(int index):获取指定index位置的元素;
  • int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置;
  • Object remove(int index):移除指定index位置的元素,并返回此元素;
  • Object set(int index ,Object ele):设置指定index位置的元素为ele;
  • List subList(int fromIndex ,int toIndex):返回fromIndex到toIndex位置的子集合;
Set接口
  1. HashSet:作为Set接口的主要实现类:线程不安全;可以存储null值;
  2. LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历;
  3. TreeSet:可以按照添加对象的指定元素,进行排序;
  4. Set接口:存储无序的、不可重复的数据;

以HashSet为例:

  • 无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的;
  • 不可重复性:保证添加的元素按照equals()判断时,不能返回true;
添加元素的过程:以HashSet为例:
  1. 我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即:索引位置),判断数组此位置上是否已经有元素:
  • 如果此位置上没有其他元素,则元素a添加成功; ---->情况1

  • 如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值;

  • 如果hash值不相同,则元素a添加成功;---->情况2

  • 如果hash值相同,进而需要调用元素a所在类的equals()方法;

​ equals()返回true,元素a添加失败;

​ equals()返回false,则元素a添加成功;----->情况3

  1. 对于添加成功的情况2和情况3而言:元素a与已经存在指定索引位置上数据以链表的方式存储;
  • jdk 7:元素a放到数组中,指向原来的元素;
  • jdk 8:原来的元素在数组中,指向元素a;
  • 总而言之:七上八下
  1. Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法;
  2. 要求:向Set中添加的数据,其所在的类一定要重写hashCode()和equals();
  3. 要求:重写的hashCode()和equals()尽可能保持一致:相等的对象必须具有相等的散列码;
TreeSet
  1. 向TreeSet中添加的数据,要求是相同类的对象;
  2. 两种排序方式:自然排序(实现Comparable接口)和定制排序(Comparator);
  3. 自然排序中,比较两个对象是否相同的标准为:comoaraTo()返回0,不再是equals();
  4. 定制排序中,比较两个对象是否相同的标准为:comoara()返回0,不再是equals();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值