Java集合框架

来源:互联网 发布:mysql 分组 每组数量 编辑:程序博客网 时间:2024/05/18 01:04

先来看一张Java集合的类图。本来是想自己画一个的,但是在网上看到了这个图之后就觉得没有再重新画一个的必要了。这个图相对网上其他一些图来说更全面一些。

Java集合框架

下面我们根据这个图来逐一分析具体的常用集合类。

  • Iterator接口:这个接口定义了从集合中获取元素和判断集合中是否还有元素的方法。下图中是jdk1.8中Iterator接口申明的两个方法

通过hasNext()方法可以判断集合中是否还有剩余元素,next()则可以将下一个元素取出。
当然该接口使用了Java8带来的一些新特性,比如接口中的这个方法

在接口中通过default关键字给出了方法的默认实现,并且好像还有了些函数式编程的意味,没错!这都是Java8的新特性,不过这些都不在本文的讨论范围,这里我们只谈Java集合框架。

  • ListIterator接口:该接口是Iterator的子接口,它可以让程序员从不同的方向遍历列表,这个迭代器的光标位置在调用 previous() 所返回的元素和调用 next() 所返回的元素之间。所以调用next()或者previous()方法返回的都是迭代器光标所越过的元素。

  • Collection接口:Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。该接口定义了一些最基本的集合操作的方法。

  • Queue接口:规定了队列操作需要的方法。LinkedList实现了Queue接口,使用Queue接口可以窄化LinkedList中方法的调用。这种方式会使程序有更好的可读性,并且也更安全。

  • Deque接口:Queue的子接口,它规定了双向队列操作需要的方法。

  • List接口:List是有顺序的集合,元素可以重复,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(类似于数组下标)来访问List中的元素。

  • LinkedList类:该类实现了List接口,并允许null元素,这个实现是基于链表的,下图是LinkList的私有静态内部类Node的源码,一个Node表示链表的一个节点。根据源码也可以看出这是一个双向链表。

  • ArrayList类:实现了List接口,允许null元素,该类的实现是基于数组的,但是可以根据需要自动的扩充数组的大小。

  • Vector类:和ArrayList类似,不同之处在于Vector是线程安全的。

  • Stack类:继承自Vector,实现了后进先出的栈数据结构。

  • Set接口:不包含重复元素的集合。

  • HashSet类:这个类的实现是基于HashMap的。下面两张图是HashSet的部分源码

HashSet构造方法
HashSet中的add方法

由这两张图可以看出,在HashSet内部,是通过HashMap的Key来存储元素的,而HashMap的Value始终存储的是PRESENT对象。由此可见,该集合会浪费一些内存。

  • TreeSet类:TreeSet是一个有序的集合,其实现基于TreeMap(类似于HashSet基于HashMap实现)。TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间大小关系,然后将集合元素按升序排列。如果试图把一个对象添加进TreeSet时,则该对象的类必须实现Comparable接口。

  • Map接口:该接口并没有继承自Collection,它提供一种key到value的映射。该接口提供了3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。

  • TreeMap类:基于红黑树实现。通过给定的或默认的Comparator(自然顺序)排序Keys,每一个key-value作为红黑树的一个节点。下图就是TreeMap的部分源码。

TreeMap部分源码

  • HashMap类:HashMap是一个散列表,它存储的内容是键值对(key-value)映射。有两个参数影响HashMap的性能:“初始容量” 和 “加载因子”。容量是散列表中桶的数量。加载因子是散列表在其容量自动增加之前可以达到多满的一种尺度。当散列表中的条目数超出了加载因子(默认0.75)与当前容量的乘积时,就会对散列表进行再哈希(rehash)操作。通过拉链法解决散列冲突的思想如下图

该图中的数组下标可以看作是每一个桶的标号,需要注意的是,每一个桶中存放的元素也是键-值对,而不是仅仅有值。否则当一个桶中有多个值的时候就无法通过键来确定值(如果两个键相同,则它们的hash值一定相同;但是如果hash值相同,那么两个键不一定相同。即a.equals(b)==true是a.hashCode()==b.hashCode()的充分不必要条件)。

  • WeakHashMap类:其中存放了对键对象的弱引用,当除了自身有对key的弱引用外,此key没有其他引用,那么就会自动丢弃此值。只具有弱引用的对象拥有更短暂的生命周期。垃圾回收器线程一旦发现了只具有弱引用的对象,就会回收它的内存。

  • Hashtable类:继承自Dictionary类,并实现了Map接口,它的Key和Value不允许为null。和HashMap不同,该类是线程安全的。

哇塞!一直觉得这些知识挺基础的,今天总结了一下,发现还是有很多细节没有弄清楚,就这样边查资料边看源码边总结,从下午到晚上这几个小时下来也是收获颇丰!看来真是:“纸上得来终觉浅,绝知此事要躬行”啊。

0 0
原创粉丝点击