java知识总结——容器

说明

  本文仅仅为了博主面试时方便查阅与梳理相关知识,如果有错误与不到位的地方,欢迎大佬指点改正,谢谢!
  阅读书籍:《java程序员面试笔试宝典》

一、java Collection框架

  java Collection框架中包含了大量集合接口以及这些接口的实现类和操作它们的算法。具体而言,主要提供了List(列表)、Queue(队列)、Set(集合)、Stack(栈)和Map(映射表,用于存放键值对)等数据结构。其中,List、Queue、Set、Stack都继承自Collection接口。
  Collection是整个集合框架的基础,它里面储存一组对象,表示不同类型的Collections,它的作用只是提供维护一组对象的基本接口。
  1、Set
  Set最主要的特点是集合中的元素不能重复,因此存入Set的每个元素都必须定义equals()方法来确保对象的唯一性。该接口有两个实现类:HashSet和TreeSet。其中TreeSet实现了SortedSet接口,因此TreeSet容器中的元素是有序的。
  2、List
  List又称为有序的Collection。它按对象进入的顺序保存对象,所以它能对列表中的每个元素插入和删除位置进行精确的控制。同时,它可以保存重复的对象。LinkedList、ArrayList和Vector都是些了List接口。
  3、Map
  Map提供了一个从键映射到值的数据结构。它用于保存键值对,其中值可以重复,但键是唯一的,不能重复。java类库中有多个实现该接口的类:HashMap、TreeMap、LinkedHashMap、WeakHashMap、IdentityHashMap。
  虽然他们都实现了相同的接口,但执行效率却不是相同的。具体而言,HashMap是基于散列表实现的,采用对象的HashCode可以进行快速查询。LinkedHashMap采用列表来维护内部的顺序。TreeMap基于红黑树的数据结构来实现的,内部元素是按需排列的

二、迭代器

  迭代器是一个对象,它的工作是遍历并选择序列中的对象,它提供了一种访问一个容器对象中的各个元素,而又不必暴露该对象内部细节的方法。迭代器通常被称为轻量级的容器。
  迭代器的使用注意有以下3个方面的注意事项:
  1、使用容器的iterator()方法返回一个Iterator,然后通过Iterator的next()方法返回第一个元素。
  2、使用Iterator的hasNext()方法判断容器中是否还有元素,如果有,可以使用next()方法获取下一个元素。
  3、可以通过remove()方法删除迭代器返回的元素。
  注意:Iterator支持派生的兄弟成员。ListIterator只存在于List中,支持在迭代期间向List中添加或删除元素,并且可以在List中双向滚动。
  注意:在遍历的过程中把需要删除的对象保存到一个集合中,等遍历结束后在调用removeAll()方法来删除,或者使用iter.remove()方法。

  Iterator和ListIterator的区别
  Iterator只能正向遍历集合,适用于获取移除元素。ListIterator继承自Iterator,专门针对List,可以从两个方向来遍历List,同时支持元素的修改。

三、ArrayList、Vector和LinkedList

  ArrayList、Vector、LinkedList类均在java.util中,均为可伸缩数组,即可以动态改变长度的数组。
  ArrayList和Vector都是基于存储元素的Object[] array来实现的,它们会在内存中开辟一块连续的空间的来存储,由于数据存储是连续的,因此,它们支持用序号(下标)来访问元素,同时索引数组的速度比较快。但是在插入元素时需要移动容器中的元素,所以对数据的插入操作执行的比较慢。
  ArrayList和Vector都有一个初始化的容量的大小,当里面存储的元素超过这个大小时就需要动态地扩充它们的存储空间。为了提高程序的效率,每次扩充容量,不是简单地扩充一个存储单元,而是一次增加多个存储单元。Vector默认扩充为原来的2倍(每次扩充空间的大小时可以设置的),而ArrayList默认扩充为原来的1.5倍(没有提供方法来设置空间扩充的方法)。
  ArrayList与Vector最大的区别就是synchronized(同步)的使用,没有一个ArrayList的方法是同步的,而Vector的绝大多数方法都是直接或者间接同步的,所以Vector是线程安全的,ArrayList不是线程安全的。正是由于Vector提供了线程安全的机制,其性能上也要略逊与ArrayList
  LinkedList是采用双向列表来实现的,对数据的索引需要从列表头开始遍历,因此用于随机访问效率比较低,但是插入元素时不需要对数据进行移动,因此插入效率较高。同时,LinkedList是非线程安全的容器
  当对数据的主要操作为索引或只在集合的末端增加、删除元素时,使用ArrayList或Vector效率比较高;当对数据的操作主要为指定位置的插入或删除操作时,使用LinkedList效率比较高;当在多线程中使用容器时(即多个线程会同时访问该容器),选用Vector较为安全

四、HashMap、Hashtable、TreeMap和WeakHashMap

  java为数据结构中的映射定义了一个接口java.util.Map,它包括3个实现类:HashMap、Hashtable和TreeMap。Map是用来存储键值对的数据结构,在数组中通过数组下标来对其内容索引的,而在Map中,则是通过对象来进行索引,用来索引的对象叫做key,其对应的对象叫做value
  HashMap是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap与Hashtable都采用了hash法进行索引,区别如下:
  1、HashMap是Hashtable的轻量级实现(非线程安全的实现),它们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key)。注意:最多只允许一条记录的键为null,不允许多条记录的值为null。而Hashtable不允许。
  2、HashMap把Hashtable的contains方法去掉了,改成contansvalue和containsKey,因为contains方法容易让人引起误解。Hashtable继承自Dictionary类,HashMap是Map接口的一个实现
  3、Hashtable的方法是线程安全的,而HashMap不支持线程的同步,所以它不是线程安全的。在多个线程访问Hashtable时,不需要开发人员对它进行同步,而对于HashMap,开发人员必须提供额外的同步机制。就效率而言,HashMap可能高于Hashtable
  4、Hashtable使用Enumeration,HashMap使用Iterator。
  5、Hashtable和HashMap采用的hash/rehash算法都几乎一样,所以性能不会有很大的差异。
  6、在Hashtable中,hash数组默认大小是11,增加的方式是old+old+1。在HashMap中,hash数组的默认大小是16,而且一定是2的指数。
  7、hash值的使用不用,Hashtable直接使用对象的hashCode。
  HashMap里面存入的键值对在取出时没有固定的顺序,是随机的。
  一般而言,在Map中插入、删除和定位元素,HashMap是最好的选择。由于TreeMap实现了SortMap接口,能够把它保存的记录根据键排序,因此,取出来的是排序后的键值对,如果需要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。LinkedHashMap是HashMap的一个子类,如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列。
  WeakHashMap与HashMap类似,二者的不同之处在于WeakHashMap中Key采用的是“弱引用”的方式,只有WeakHashMap中的key不再被外部引用,它就可以被垃圾回收器回收。而HashMap中key采用的是“强引用的方式”,当HashMap中的key没有被外部引用时,只有在这个key从HashMap中删除后,才可以被垃圾回收器回收。

  在Hashtable上下文中,同步指的是什么?
  同步意味着在一个时间点只能有一个线程可以修改hash表,任何线程在执行Hashtable的更新操作前都需要获取对象锁,其他线程则等待锁的释放。

  如何实现HashMap的同步?
  HashMap可以通过Map m = Collectons.synchronizedMap(new HashMap())来达到同步的效果。具体而言,该方法返回一个同步的Map,该Map封装了底层的HashMap的所有方法,使得底层的HashMap即使是在多线程的环境中也是安全的。

五、用自定义类型作为HashMap或Hashtable的key需要注意哪些问题

  HashMap与Hashtable是用来存放键值对的一种容器,在使用这两个容器时由一个限制:不能用来存储重复的键。也就是说,每个键只能唯一映射一个值,当有重复的键时,不会创建新的映射关系,而会使用先前的键值
  开发者在使用自定义类作为HashMap的key时,需要注意以下几个问题:
  1、如果想根据对象的相关属性来自定义对象是否相等的逻辑,此时就需要重写equals()方法,一旦重写了equals()方法,那么就必须重写hashCode()方法
  2、当自定义类的多项作为HashMap(Hashtable)的key时,最好把这个类设计为不可变类。
  3、从HashMap的工作原理可以看出,如果两个对象相等,那么这两个对象有着相同的hashCode(),反之则不成立。

六、Collection和Collections

  1、Collection
  Collection是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法。实现该接口的类主要有List和Set,该接口的设计目标是为各种具体的集合提供最大化的统一的操作方式。
  2、Collections
  Collections是针对集合类的一个包装类,它提供一系列静态方法以实现对各种集合的搜索、排序、线程安全化等操作,其中大多数方法都是用来处理线性表。Collections类不能实例化,如同一个工具类,服务于Collection框架。若在使用Collections类的方法时,对应的collection的对象为null,则这些方法都会抛出NullPointerException。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值