集合学习看这一个就够了

一、集合概述

一、集合框架的概述

1.集合、数组都是对多个数据进行存储操作的结构,简称java容器。

说明:这里说的存储,主要是内存层面的存储,不涉及持久化的存储。

2.1数组在存储方面的特点(两者相比较)

           一旦初始化以后,其长度就确定了。言外之意 这是一个缺点

          数组一旦定义好之后,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。例如:String[] arr ;int [] arr;等等。

2.2数组在存储方面的缺点:

          初始化之后,长度确定了,不可以修改了。

          数组中提供的方法比较少,对与删除插入数据等操作,非常不便,效率不高。 

          获取数组中实际元素的个数的需求,数组中没有现成的属性或方法可以使用

          数组存储数据有序、可重复。对与无序、不重复的需求,数组是不能满足的。

 

二、java的集合体系、集合框架:

collection接口  实线代表继承,虚线代表实现类

map的体系

 

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

         List接口:有序的可重复的数据。习惯上吧List称作动态数组。

                       ArrayList/LinkedList/Vector              

         Set接口:无序的不可重复的数据

                       HashSet/LinkedHashSet/TreeSet

Map接口:双列接口  k-v的存储形式。

                       HashMap/LinkedHashMap/TreeMap/HashTable/Properties

二、Collection

Collection接口中的常见方法:

Iterator:集合元素遍历接口  迭代器

Iterator对象成为迭代器(设计模式中的 一种),主要用于遍历Collection集合中的元素。

迭代器模式定义为:提供一种方法访问容器Collection对象中各个元素,而又不暴露该对象内部细节。迭代器模式就是为容器而生。

用法:

foreach:for循环的增强,用于遍历集合数组。

foreach内部原理仍是调用的迭代器

 

List

比较ArrayList/LinkedList/Vector三者之间的异同:

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

不同:ArrayList作为List的主要实现类,执行效率比较高,效率不安全。底层依旧使用Object[]存储。

          LinkedList:底层使用双向链表,对与频繁的插入删除操作,使用此类效率较高。

           Vector作为List的古老实现类,jdk1.0就出现了,作为List接口出现之前的实现有序可重复存储的方法。线程安全的效率低syn。底层使用Object[]存储。

ArrayList

源码分析:jdk7和jdk8有差距

jdk7:

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(int capacity);//直接定义好数组长度,从而尽可能的避免扩容。

 

jdk8:

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

list.add(123);//第一次创建了长度为10的数组,并将数据添加到elementData

....

后续的添加和扩容操作 与jdk7没有区别

jdk7与jdk8的总结:

7是类似于饿汉式创建对象,8是类似于懒汉式创建,延迟了数组的创建,节省内存。

LinkedList

源码分析:

LinkedList list =new LinkedList()//内部声明了Node类型的first和last属性,默认值为null。

list.add(123) //将123封装到Node中,创建了Node对象。

其中Node定义为:

可以确定 Node确实是双向链表

Vector(忽略了)

扩容方式有不同:默认为2倍。

Set

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

         Set接口:无序的不可重复的数据

                       HashSet:作为Set接口的主要实现类,线程不安全。

                                     LinkedHashSet:是HsahSet的子类。遍历内部数据时,是按照添加顺序来的(不是有序)。

                      TreeSet:使用红黑树存的,可以按照添加对象的属性,进行排序。

理解Set的无序性和不可重复性:

无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值判断

不可重复性:保证添加的元素按照equals()判断时,不能返回true.相同元素只能添加一个。

添加元素的过程:以HashSet为例:

添加第一个数据,由于里面没有数据,那么直接添加即可,

添加第二个需要调用equals方法进行比较,返回false,才能进行添加,

添加第三个数据需要和前两个数据依次比较。

....

添加第1000个数据,就需要和前999个数据都进行比较。

这样来说,效率就会很低。

Set用了一种巧妙地方式进行实现,

我们向HashSet中添加a

首先调用元素a所在类的HashCode()方法,计算元素a的哈希值,此哈希值接着通过某种算法计算出在HashSet底层数组中存放的位置(索引位置)是否已经有元素,

如果此位置上没有元素,则直接添加成功。

如果此位置上已经有元素b或以链表形式存在其他元素,则比较元素a与b的哈希值

        如果哈希值不相同,则添加a成功

        如果相同

                调用元素a的equals()方法

                        方法返回true  添加失败

                       方法返回false  添加成功

对与添加成功这样的情况:a和制定索引位置上数据以链表形式存储

jdk7:元素a存放到数组中,指向原来的元素

jdk8:原来的元素指向a

 

注意:

1、Set接口没有额外定义新的方法,使用的都是Collection中声明的方法。

2、要求:向set中添加的数据,其所在的类一定要重写hashCode()和equals()

               重写的hashCode()和equals()尽可能保持一致性:相等对象必须具有相等的散列码。

 

HashSet

LinkedHashSet

LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个引用,记录此前数据前一个数据和后一个数据。

优点:对与比较频繁的便利操作要优于HashSet

TreeSet

 

可以按照添加对象的指定属性,进行排序。

1、向TreeSet中添加的数据,要求是相同的类的对象。

2、两种排序方式:

自然排序实现CompareTo接口,和定制排序实现Comparator

 

三、Map

除了SortedMap都是他的实现类

Map:双列结构,存储k-v对的数据

       HashMap:主要实现类

 

              LinkedHashMap:

       TreeMap:

       Hashtable:古老实现类

               Properties:

hashmap和hashtable的区别:https://blog.csdn.net/wangxing233/article/details/79452946

hashmap源码分析:https://blog.csdn.net/qq_43925089/article/details/107134607

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值