​(九)JAVA基础及提高篇集合类详细说明

1.什么是Java集合类?

集合类是Java数据结构的实现。Java集合类是java.util包中的重要内容,它允许以各种方式将元素分组,并定义了各种使这些元素更容易操作的方法。Java集合类是Java将一些基本的和使用频率极高的基础类进行封装和增强后再以一个类的形式提供。集合类是可以往里面保存多个对象的类,存放的是对象,不同的集合类有不同的功能和特点,适合不同的场合,用以解决一些实际问题。

框架图:

1.1 什么是Java集合API?

  Java集合框架API是用来表示和操作集合的统一框架,它包含接口、实现类、以及帮助程序员完成一些编程的算法。简言之,API在上层完成以下几件事:

  ● 编程更加省力,提高城程序速度和代码质量

  ● 非关联的API提高互操作性

  ● 节省学习使用新API成本

  ● 节省设计新API的时间

  ● 鼓励、促进软件重用

        具体来说,有6个集合接口,最基本的是Collection接口,由三个接口Set、List、SortedSet继承,另外两个接口是Map、SortedMap,这两个接口不继承Collection,表示映射而不是真正的集合

1.2 什么是Iterator?

  一些集合类提供了内容遍历的功能,通过java.util.Iterator接口。这些接口允许遍历对象的集合。依次操作每个元素对象。当使用 Iterators时,在获得Iterator的时候包含一个集合快照。通常在遍历一个Iterator的时候不建议修改集合本省。

  • Iterator:只能正向遍历集合,适用于获取移除元素。
  • ListIerator:继承Iterator,可以双向
    列表的遍历,同样支持元素的修改。

2.集合和数组的区别

è¿éåå¾çæè¿°

3.Collection集合的方法

è¿éåå¾çæè¿°

4.常用集合的分类(总结)

Java集合框架主要包括两种类型的容器,一种是集合(Collection),另一种是图(Map)。

Collection 接口的接口 对象的集合(单列集合) 
├——-List 接口:元素按进入先后有序保存,可重复 
│—————-├ LinkedList 接口实现类, 底层数据结构是链表, 插入删除, 没有同步, 线程不安全 
│—————-├ ArrayList 接口实现类, 底层数据结构是数组, 随机访问, 没有同步, 线程不安全 
│—————-└ Vector 接口实现类 底层数据结构是数组, 同步, 线程安全 
│ ———————-└ Stack 是Vector类的实现类 
└——-Set 接口: 仅接收一次,不可重复,并做内部排序 
├—————-└HashSet 使用底层使用hash表(数组)存储元素 (无序)
│————————└ LinkedHashSet 链表维护元素的插入次序 (FIFO,由链表保证元素有序,哈希表保证元素唯一)
└ —————-TreeSet 底层实现为二叉树(红黑树),元素排好序(根据比较的返回值是否是0来决定元素是否唯一)

Map 接口 键值对的集合 (双列集合) 
├———Hashtable 接口实现类, 同步, 线程安全 
├———HashMap 接口实现类 ,没有同步, 线程不安全- 
│—————–├ LinkedHashMap 双向链表和哈希表实现 
│—————–└ WeakHashMap 
├ ——–TreeMap 红黑树对所有的key进行排序 (有序)
└———IdentifyHashMap

注意:Hashtable不允许null值,HashMap允许null值(key和value都允许)

4.1 List和Set集合详解

4.1.1 list和set的区别

è¿éåå¾çæè¿°

4.1.2 List
(1)ArrayList:底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素 
(2)LinkedList 底层数据结构是链表,查询慢,增删快,线程不安全,效率高,可以存储重复元素 
(3)Vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素 

è¿éåå¾çæè¿°

  • ArrayList与LinkedList的区别和适用场景

Arraylist: 
优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。 
缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。

LinkedList: 
优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景 
缺点:因为LinkedList要移动指针,所以查询操作性能比较低。 

4.1.3 set

  1. HashSet:底层数据结构采用哈希表实现,元素无序且唯一,线程不安全,效率高,可以存储null元素,但只能放入一个null,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。
  2. LinkedHashSet:底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。 
  3. TreeSet:底层数据结构采用二叉树来实现,元素唯一且已经排好序,不允许放入null值 ;唯一性同样需要重写hashCode和equals()方法,二叉树结构保证了元素的有序性。根据构造方法不同,分为自然排序(无参构造)和比较器排序(有参构造),自然排序要求元素必须实现Compareable接口,并重写里面的compareTo()方法,元素通过比较返回的int值来判断排序序列,返回0说明两个对象相同,不需要存储;比较器排需要在TreeSet初始化是时候传入一个实现Comparator接口的比较器对象,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法; 
  4. 适用场景分析:HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。为快速查找而设计的Set,我们通常都应该使用HashSet,在我们需要排序的功能时,我们才使用TreeSet。 

4.2 Map详解

Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复。所以通过指定的key就可以取出对应的value。而HashMap是用哈希算法实现Map的具体实现类,别搞混了。

1 HashMap

  • HashMap是基于哈希表的Map接口的非同步实现,继承自AbstractMap,AbstractMap是部分实现Map接口的抽象类。在平时的开发中,HashMap的使用还是比较多的。我们知道ArrayList主要是用数组来存储元素的,LinkedList是用链表来存储的,那么HashMap的实现原理是什么呢?先看下面这张图:
  • 在之前的版本中,HashMap采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当链表中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,HashMap采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
  • HashMap数据结构图:

  • 在HashMap中要找到某个元素,需要根据key的hash值来求得对应数组中的位置。对于任意给定的对象,只要它的hashCode()返回值相同,那么程序调用hash(int h)方法所计算得到的hash码值总是相同的。我们首先想到的就是把hash值对数组长度取模运算,这样一来,元素的分布相对来说是比较均匀的。但是,“模”运算的消耗还是比较大的,在HashMap中,(n - 1) & hash用于计算对象应该保存在table数组的哪个索引处。HashMap底层数组的长度总是2的n次方,当数组长度为2的n次幂的时候,(n - 1) & hash 算得的index相同的几率较小,数据在数组上分布就比较均匀,也就是说碰撞的几率小,相对的,查询的时候就不用遍历某个位置上的链表,这样查询效率也就较高了。

  • 关于HashMap有一篇博客讲的很细,可以去参考:一个HashMap跟面试官扯了半个小时_安琪拉的博客-CSDN博客

2.LinkedHashMap

LinkedHashMap继承自HashMap,它主要是用链表实现来扩展HashMap类,HashMap中条目是没有顺序的,但是在LinkedHashMap中元素既可以按照它们插入图的顺序排序,也可以按它们最后一次被访问的顺序排序。

3.TreeMap

TreeMap基于红黑树数据结构的实现,键值可以使用Comparable或Comparator接口来排序。TreeMap继承自AbstractMap,同时实现了接口NavigableMap,而接口NavigableMap则继承自SortedMap。SortedMap是Map的子接口,使用它可以确保图中的条目是排好序的。

在实际使用中,如果更新图时不需要保持图中元素的顺序,就使用HashMap,如果需要保持图中元素的插入顺序或者访问顺序,就使用LinkedHashMap,如果需要使图按照键值排序,就使用TreeMap。
 

HashMap和HashTable的比较: 

è¿éåå¾çæè¿°

小结1

  1. HashMap和HashTable:HashMap去掉了HashTable的contains方法,但是加上了containsValue()和containsKey()方法。HashTable同步的,而HashMap是非同步的,效率上比HashTable要高。HashMap允许空键值,而HashTable不允许。
  2. HashMap:适用于Map中插入、删除和定位元素。 
  3. Treemap:适用于按自然顺序或自定义顺序遍历键(key)。
  4. LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的; 
  5. HashMap,TreeMap是非线程安全的,HashTable是线程安全的; 
  6. StringBuilder是非线程安全的,StringBuffer是线程安全的。
  7. HashMap可以通过Map m = Collections.synchronizedMap(hashMap)来达到同步的效果。

小结2   各个集合的特点(来自java编程思想)

  1. List. ArrayList 和LinkedList都是按照被插入的顺序保存元素,在性能上,ArrayList利用索引号访问集合元素,所以比较适合随机访问元素;LinkedList基于链表的结构,在插入和删除方面性能比ArrayList高,并提供了顺序访问的优化,在顺序访问上,性能和ArrayList相差无几,但是随机访问方面比较慢。
  2. Set.  HashSet, TreeSet, LinkedHashSet,set是不重复的, 获取最快的是HashSet,但是不按照存放先后进行存储; TreeSet会按照比较结果的升序保存对象;LinkedHashSet按照被添加的顺序保存对象。
  3. Map. HashMap, TreeMap, LinkedMap, 与Set一样, HashMap提供了最快的查询速度,TreeMap提供了按照比较结果的升序进行保存key值,LinkedHashMap按照插入的顺序保存Key, 并且保存了HashMap的查询速度。

 5.集合问题测验

问题1.常见的集合有哪些:

Map接口和Collection接口是所有集合框架的父接口

List接口的实现类主要有:ArrayList、LinkedList、Vector、Stack(Vector的子类)等

Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet(HashSet的子类)等

Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等

问题2.List、Set和Map接口的特点

1)Set表示数学意义上的集合概念,所以其主要特点是集合中的元素不能重复,存储时无序

2)List称为有序的collection。它按对象进入的顺序保存对象,同时,它可以保存重复的对象

3)Map用于保存键值对,其中value可以重复,但键不能重复

问题3.ArrayList、Vector和LinkedList的联系和区别?

ArrayList和Vector都是基于存储元素的Obeject[] array来实现的,它们会在内存中开辟一块连续的空间来存储,

由于数据存储时连续的,所以支持用下标来访问元素,索引数据的速度比较快。

但是在插入元素时需要移动容器中的元素,因此对数据的插入操作执行得较慢

区别:1)同步性:ArrayList的方法都是不同步的,而Vector的绝大多数方法(如add、insert、remove、set、equals、hashcode等)

都是直接或间接同步的,所以Vector是线程安全的,ArrayList不是线程安全的(正是由于Vector提供了线程安全的机制,其性能上要稍逊于ArrayList)

2)扩容大小:Vector默认扩充为原来的2倍(每次扩充空间的大小是可以设置的),ArrayList默认扩充为原来的1.5倍(没有提供方法来设置空间扩充的大小)

LinkedList是采用双向列表来实现的,对数据的索引需要从列表头开始遍历,因此随机访问效率较低,但是插入元素不需要对

数据进行移动,因此插入效率较高。同时,它是非线程安全的容器

扩展:当增删操作在末尾来操作(remove()和add()方法),此时ArrayList不需要移动数组元素,所以效率比LinkedList要高

当对数据的操作主要为指定位置的插入或删除时,使用LinkedList效率比较高

问题4.HashMap、HashTable的区别

1)HashMap没有考虑同步,是线程不安全的;Hashtable使用了synchronized关键字,是线程安全的

2)HashMap允许null作为Key和Value;HashTable key和value都不能为null

3)HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。 

4)hash值的使用不同,HashTable直接使用对象的hashCode,HashMap重新计算hash值

5)hash数组默认大小不同,HashMap中,hash数组的默认大小时16,扩容时增加为原来的2倍,HashTable中默认大小是11,增加

方式为原来的2倍加1.

6)遍历方式不同。Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式

问题5.HashMap是如何实现key唯一的

在HashMap的put方法实现中首先利用了hash()生成key的hashCode,生成一个hash值h1,如果这个h1在HashMap中不存在,那么直接将<key,value>添加
到HashMap中;如果这个值已经存在,那就会找出来HashMap中所有hash值为h1的key,然后分别调用key的equals()方法判断当前谈价的key值是否与
已经存在的key值相同,如果equals()方法返回true,HashMap会使用新的value值来覆盖掉旧的value值,如果equals()方法返回false,说明新增加的key
在HashMap中不存在,因此会在HashMap中创建新的映射关系
哈希冲突:不同的key值有相同的hash值

问题6.Java中HashMap的key值要是为类对象则该类需要满足什么条件?

需要同时重写该类的hashCode()方法和它的equals()方法

问题7.如何实现HashMap的同步

可以通过Map m=Collections.synchronizedMap(new HashMap())来达到同步的效果

问题8.Collection和Collections的区别

1)Collection是一个集合接口,继承它的接口为List和Set

2)Collections是针对集合类的一个包装类,提供了一系列的静态方法实现对集合的搜索、查找、同步等操作

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值