集合类总结

来源:互联网 发布:神通数据库 7.0 下载 编辑:程序博客网 时间:2024/05/22 06:23

这里写图片描述
一、Collection接口:
Collection是最基本的集合接口,一个Collection代表一组Object对象的引用,即Collectio并不直接储存对象,而是存储的是对象的引用。JAVA JDK并不直接提供继承Collection的类,即没有具体的实现,JDK提供的实现类都是继承了集合Collection的两个子接口:List 和 Set。
Collection的任何实现都必须提供两个构造方法:
1. 无参构造,默认创建一个空集合
2. 有参构造,允许传一个参数(集合 ),新建的集合元素和传入的集合元素一样!

无论集合元素是什么类型,都可以用迭代器来遍历集合,需注意在迭代遍历集合的过程中,不能用集合的方法对集合进行增删操作,遍历过程中可以种迭代器自带的remove()方法,删除集合元素

  1. 迭代器,每个集合都有自己的iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:
Iterator it = collection.iterator();    while(it.hashnext())    {        Object obj = it.next();    }
  1. for增强:底层代码也是由迭代器实现,例如:
Collection<String> collection = new ArrayList<String>();        for(String s :collection){//遍历集合中的每个元素,并返回该元素            System.out.println(s);        }

建议写集合的时候,一般写成向上造型结构:例如

//都是用的集合的方法,可以省去很多麻烦Collection<String> collection = new ArrayList<String>();

二、集合子接口List

这里写图片描述

List集合常用实现类:

这里写图片描述

有序的Collection成为序列;

List实现类的底层实现是数组,因此List具有一些数组的特性,比如有序可重复,亦可通过下标索引来访问元素,List的索引也是从0开始。注意,这些操作可能在和某些实现(例如 LinkedList 类)的索引值成比例的时间内执行。因此,如果调用方不知道实现,那么在列表元素上迭代通常优于用索引遍历列表。

List 接口提供了特殊的迭代器,称为 ListIterator,除了允许 Iterator 接口提供的正常操作外,该迭代器还允许元素插入和替换,以及双向访问。还提供了一个方法来获取从列表中指定位置开始的列表迭代器。

void add(int index, Object element) boolean addAll(int index, Collection collection) Object get(int index) int indexOf(Object element) int lastIndexOf(Object element) Object remove(int index) Object set(int index, Object element)

三、集合子接口Set

这里写图片描述

Set常用实现类:

这里写图片描述
3.1 Set实现类的特点:无序,不可重复,底层Hash表实现,存取速度快,线程不安全。
3.2 HashSet及HashMap的Hash储存机制:
HashSet和HashMap 两者有很多相似之处,对于HashSet而言,系统采用Hash算法,计算元素下标,界定元素储存的位置,这样可以保证快速存取集合元素。
对于HashMap而言,系统把 key-value键对,当成一个整体,系统总是根据Hash算法计算键对的下标,决定储存位置,这样可以快速存取Map的key-value对。

四、集合子接口Map:

这里写图片描述
Map常用实现类:

这里写图片描述

4.1 HashMap存储实现
要知道Hashmap是什么,首先要搞清楚它的数据结构,在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,Hashmap也不例外。Hashmap实际上是一个数组和链表的结合体(在数据结构中,一般称之为“散列存储“),请看下图:横排表示数组,纵排表示数组元素(实际上是一个链表结构)。

这里写图片描述

从图中看出一个Hashmap就是一个数组结构,当新建一个Hashmap的时候,就会初始化一个数组,而每个数组元素对应的是一个链表引用

往Hashmap中put元素:
① 先根据key的hash值得到这个元素在数组中的位置(即下标),然后把这个元素放到对应的位置中了。
② 如果这个元素所在的位子上已经存放有其他元素了,那么在同一个位子上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。

从hashmap中get元素:
① 首先计算key的hashcode,找到数组中对应位置的某一元素;
② 然后通过key的equals方法在对应位置的链表中找到需要的元素。
从这里我们可以想象得到,如果每个位置上的链表只有一个元素,那么hashmap的get效率将是最高的。

归纳起来简单地说,HashMap 在底层将key-value 当成一个整体进行处理,这个整体就是一个Entry 对象。HashMap 底层采用一个Entry[] 数组来保存所有的key-value对,当需要存储一个Entry 对象时,会根据Hash 算法来决定其存储位置;
当需要取出一个Entry 时,也会根据Hash 算法找到其存储位置,直接取出该Entry。

当创建HashMap 时,有一个默认的负载因子(load factor),其默认值为0.75,这是时间和空间成本上一种折衷:增大负载因子可以减少Hash 表(就是那个Entry 数组)所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的的操(HashMap 的get() 与put() 方法都要用到查询);减小负载因子会提高数据查询的性能,但会增加Hash表所占用的内存空间。
因此,我们可以在创建HashMap 时根据实际需要适当地调整loadfactor 的值;如果程序比较关心空间开销、内存比较紧张,可以适当地增加负载因子;如果程序比较关心时间开销,内存比较宽裕则可以适当的减少负载因子。通常情况下,程序员无需改变负载因子的值。如果开始就知道HashMap 会保存多个key-value 对,可以在创建时就使用较大的初始化容量,如果HashMap 中Entry 的数量一直不会超过极限容量(capacity * loadfactor), HashMap 就无需调用resize() 方法重新分配table 数组,从而保证较好的性能。当然,开始就将初始容量设置太高可能会浪费空间(系统需要创建一个长度为capacity的Entry 数组),因此创建HashMap 时初始化容量设置也需要小心对待。

原创粉丝点击