7.java集合

本章要点

  • 集合的概念和作用
  • java的集合体系
  • Collection集合的常规用法
  • 使用Iterator和foreach循环遍历Collection集合
  • HashSet,LinkedHashSet的用法
  • TreeSet的用法
  • EnumSet的用法
  • List集合的常规用法
  • ArrayList和Vector
  • 固定长度的List集合
  • LinkedList集合的用法
  • Queue接口
  • PriorityQueue的用法
  • Map的概念和常规用法
  • HashMap和Hashtable
  • TreeMap的用法
  • 几种特殊的Map实现类
  • Hash算法对HashSet,HashMap性能的影响
  • Collections工具类的用法
  • Enumeration迭代器的用法

java的集合类是一种特别有用的工具类,它可以用于存储数量不等的多个对象,并可以实现常用数据结构,如栈,队列等。除此之外,java结合还可用于保存具有映射关系的关联数组。java的集合大致上可分为:Set,List和Map三种体系,其中Set代表无序,不可重复的集合list代表有序,重复的集合;而Map则代表具有映射关系的集合。从JDK1.5以后,java又增加了Queue体系集合,代表一种队列集合实现。

7.1 java集合概述

为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组),java提供集合类。集合类主要负责保存,盛装其他数据,因此集合类也被称为容器类。所有集合类都位于java.util包下。

集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量);而集合里只能保存对象(实际上也是保存对象的引用变量,但通常习惯上认为集合里保存的是对象)。

java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是java集合框架的跟接口,这两个接口又包含了一些接口或实现类。

7.2 Collection和Iterator接口

Collection接口是List,set和Queue接口的父接口,该接口里定义的方法即可用于操作set集合,也可用于操作list和queue集合。Collection接口里定义了如下操作集合元素的方法:

  • boolean add(Object o):该方法用于向集合里添加一个元素。如果集合对象被添加操作改变了则返回true。
  • boolean addAll(Collection c)
  • void clear()
  • boolean contains(Object o)
  • boolean containsAll(Collection c)
  • boolean isEmpty()
  • iterator iterator()
  • boolean remove(Object o)
  • boolean removeAll(Collection c)
  • boolean retainAll(Collection c)
  • int size()
  • Object[] toArray()

7.2.1 使用Iterator接口遍历集合元素

Iterator接口隐藏了各种Collection实现类的底层细节,向应用程序提供了遍历Collection集合元素的统一编程接口,Iterator接口里定义了如下三个方法:

  • boolean hasNext():如果被迭代的集合元素还没有被遍历,则返回true。
  • Object next():返回集合里下一个元素。
  • void remove():删除集合里上一次next方法返回的元素。

Iterator必须依附于Collection对象。有一个Iterator对象,则必然有一个与之关联的Collection对象。

7.2.2 使用foreach循环遍历集合元素

7.3 set接口

前面已经介绍过set集合,它类似于一个罐子,一旦把对象“丢进”set集合,集合里多个对象之间没有明显的顺序。set集合与collection基本上完全一样,它没有提供任何额外的方法。实际上set就是collection,只是行为不同(set不允许包含重复元素)。

set判断两个对象相同不是使用==运算符,而是根据equals方法。

7.3.1 HashSet类

HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。

HashSet具有以下的特点:

  • 不能保证元素的排列顺序,顺序有可能发生变化。
  • HashSet不是同步的,如果多个线程同时访问一个HashSet,如果有2条或者2条以上线程同时修改了HashSet集合时,必须通过代码保证其同步。
  • 集合元素值可以是null。

当向HashSet集合中存入一个元素时,hashset会调用该对象的hashCode()方法得到该对象额hashCode值,然后根据该hashCode值来决定该对象在hashSet中存储位置。如果有两个元素通过equals方法比较返回true,但它们的hashCode()方法返回值不相等,hashSet将会把它们存储在不同位置,也就可以添加成功。

简单地说,hashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值也相等。

注意:

如果需要某个类的对象保存到hashSet集合中,重写这个类的equals()方法和hashCode()方法时,应该尽量保证两个对象通过equals比较返回true时,他们的hashCode方法返回值也相等。

hashCode方法对于HashSet的作用是什么?

我们先要理解hash(也被翻译为哈希,散列)算法的功能:他能保证通过一个对象快速查找到另一个对象。hash算法的价值在于速度,它可以保证查询得到快速执行。当需要查询集合中某个元素时,hash算法可以直接根据该元素的值得到该元素保存在何处,从而可以让程序快速找到该元素。为了理解这个概念,我们先看数组(数组是所有能存储一组元素里最快的数据结构):数组可以包含多个元素,每个元素也有索引,如果需要访问某个数组元素,只需提供该元素的索引,该索引即指出了该元素在数组内存区里的存储位置。

表面上看起来,hashSet集合里的元素都没有索引,实际上当程序向hashSet集合中添加元素时,hashset会根据该元素的hashcode值来决定它的存储位置--也就是说,每个元素的hashcode就是它的“索引”。

为什么不直接使用数组,还需要使用hashSet呢?因为数组元素的索引是连续的,而且数组的长度是固定的,无法自由增加数组的长度。而hashset就不一样了,hashset采用每个元素的hashcode作为其索引,从而可以自由增加hashset的长度,并可以根据元素的hashcode值来访问元素。因此,当从hashset中访问元素时,hahsset先计算该元素的hashcode值(也就是调用该对象的hashcode()方法的返回值),然后直接到该hashcode对应的位置去取出该元素--这就是hashset速度很快的原因。

hashset中每个能存储元素的“槽位(slot)”通常称为“桶”(bucket),如果有多个元素的hashcode相同,但它们通过equals方法比较返回false,就需要在一个“桶”里放多个元素,从而导致性能下降。

重写hashCode()方法的基本规则:

  • 当两个对象通过equals方法比较返回true时,这两个对象的hashcode应该相等。
  • 对象中用做equals比较标准的属性,都应该用来计算hashcode值。

当向hashset中添加可变对象时,必须十分小心。如果修改hashset集合中的对象,有可能导致该对象与集合中其他对象相等,从而导致hashset无法准确访问该对象。

7.3.2 TreeSet类

当需要把一个对象放入treeset中时,重写该对象对应类的equals()方法时,应保证该方法与compareTo(Object obj)方法有一致的结果,其规则是:如果两个对象通过equals方法比较返回true时,这两个对象通过compareTo(Object obj)方法应返回0.

7.3.3 EnumSet 类

EnumSet是一个专为枚举类设计的集合类,EnumSet中所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式地指定。Enumset的集合元素也是有序的,EnumSet以枚举值在Enum类内的定义顺序来决定集合元素的顺序。

7.4 List接口

List集合代表一个有序集合,集合中每个元素都有其对应的顺序索引。list集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。因为list集合默认按元素的添加顺序设置元素的索引。

7.4.1 list接口和listIterator接口

7.4.2 ArrayList和Vector实现类

7.4.3 固定长度的List

7.5 Queue接口

7.6 Map

映射关系的数据

7.7 HashSet和HashMap的性能选项

7.8 操作集合的工具类:Collections

7.8.1 排序操作

7.8.2 查找,替换操作

7.8.3 同步控制

7.8.4 设置不可变集合

7.9 反锁的接口:Enumeration

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值