一.Java集合类概述
1.
集合类:为了保存数量不确定的数据,以及具有映射关系的数据(关联数组)。集合类主要负责保存和盛装其他数据,因此集合类又叫做容器类。
2.
集合类与数组的区别:
① 集合类中的数据数量不确定,而数组中数据的数量确定。
② 数组中的数据既可以是基本数据类型,又可以是对象。而集合类中只能保存对象。
3.Java
集合框架的根接口:Collection
和Map
Map
保存的的每一项数据都是一个key-value
对,其中key
是不重复的。
二.Collection
接口和Iterator
接口
1.Collection
接口
add,addAll,clear,contains,containAll,,remove,removeAll,size,isEmpty,toArray,iterator,re-tainAll
等
2.Iterator
接口
Iterator
对象被称为迭代器,用于遍历集合中的元素。
三个方法:hasNext
,next
,remove
注意:
① 使用Iterator对集合元素进行迭代时,并不是把集合元素本身赋给迭代变量,而是把集合元素的值赋给迭代变量,所以修改迭代元素的值对于集合不会有任何影响。
② 使用Iterator对集合元素进行迭代时,集合元素不能被改变(Iterator的remove方法除外),否则会产生异常。
3.foreach
循环
利用foreach
循环也可以遍历集合中的元素。
与Iterator
注意的两点相同。
三.Set
接口
Set集合类似于一个罐子,其中的元素无序且不相等。Set集合判断两个元素是否相等是根据equal方法,而不是根据“==”来判断。
1.HashSet类
HashSet
是根据哈希算法来存取集合中的元素。
HashSet
集合判断两个元素相等的标准是:通过equals
方法比较两个对象相等,并且hashCode
方法的返回值也相等。
注意:
① 如果一个类重写equals方法,那么相应的也要重写hashCode方法。规则是:如果两个对象通过equals方法比较返回true,那么它们的hashCode方法的返回值也应该相同。
② 当向HashSet集合中添加可变对象时要格外注意,因为通过对可变对象的修改可能会导致HashSet集合中的两个元素完全相同,但是又处于不同的位置,从而导致HashSet集合无法准确的访问该对象。
LinkedHashSet
类,是HashSet
的子类,与HashSet
类不同的是,它通过链表维持集合中元素的顺序,使得集合中的元素看起来时按照插入顺序保存的。
2.TreeSet
类
继承了SortedSet
接口,确保集合中的元素处于排序状态。
与HashSet
类相比增加了如下几个方法:
first,last,lower,higher,subset,headSet,tailSet,comparator
TreeSet
并不是按照元素的插入顺序进行排序,TreeSet
支持两种排序算法:自然排序和定制排序。
·自然排序:TreeSet
调用元素的compareTo
方法来比较元素的大小关系,然后按照升序排列。如果试图将一个对象加入TreeSet
集合,那么这个对象所对应的类必须实现Comparable
接口,否则会抛出异常。向TreeSet
集合中加入的必须是同一类型的对象,否则也会抛出异常。
TreeSet
集合中两个对象完全相同的标准是:通过equals
方法比较返回true
,并且同compareTo
方法比较返回0.
当向TreeSet
中加入可变对象时要格外注意,对可变对象修改后,排序不会发生变化,删除元素也可能会失败,因为TreeSet
中可能存在两个完全相同的元素。
总之,不要向HashSet和TreeSet中加入可变对象。
·定制排序:通过Comparator
接口实现。加入TreeSet
集合中的元素没有必要再实现Comparable
接口,但是加入加入TreeSet
集合中的元素仍然需要是同一类型。
3.EnumSet
类
EnumSet
是专为枚举类设计的集合类,EnumSet
集合的元素必须为指定枚举类型的枚举值。
EnumSet
没有暴露任何构造方法来构造该类的对象,要构造该类的对象必须通过EnumSet
本身提供的静态方法。
主要的静态方法如下:
allOf,noneOf,of,range,copyof(EnumSet),copyOf(Collection),complementOf
如何选择实现
Set
接口的各个类:
·
HashSet
类的性能总是比
TreeSet
类的性能要好,而
TreeSet
类在需要排序时才使用。
·
HashSet
类的性能比
LinkedHashSet
类的性能也要略好一些,但是
LinkedHashSet
类在遍历集合元素时要快一些。
·
EnumSet
是所有的
Set
实现类中性能最好的,但是只能保存枚举类型的元素。
·
Set
实现类都不是线程安全的。
四.List
接口
List
是一个有序的集合,List
集合中的每一个元素都有其对应的索引,所以List
集合中的元素允许重复。List
按照添加元素的先后顺序设置索引。
1.List
接口与ListIterator
接口
与Collection
接口不同,List
接口中增加一些根据索引操作元素的方法。
List
接口中的方法:
·添加元素:add(Object),add(index,Object),addAll(Collection),addAll(index,Collection)
·删除元素:remove(Object),removeAll(Collection),remove(index)
·获取元素:get(index)
·替换元素:set(index,Object)
·截取元素:subList(fromIndex,toIndex)
·返回索引值:indexOf(Object),lastIndexOf(Object)
ListIterator
接口是Iterator
接口的子接口,它增加了一些新的方法,专门用来操作List
集合。
ListIterator
接口中新增加的方法有:
·hasPrevious()
·previous()
·add()
2.ArrayList
和Vector
实现类
ArrayList
和Vector
类都是基于数组实现的,所以ArrayList
和Vector
都封装了一个动态分配大小的数组Object[]
。ArrayList
和Vector
类都有一个属性capacity
,表示它们封装的数组Object[]
的大小,capacity
会随集合中元素的个数变化而自动变化。
ArrayList
和Vector
类可以通过以下方法来操作capacity
属性:
·ensureCapacity(minCapacity)
·trimToSize()
Vector
类提供了一个子类Stack
类用来模拟“栈”这种数据结构。Stack
具有的方法如下:
·push(Object)
·pop()
·peek()
3.
固定长度的List
Arrays.ArrayList
类:可以将一个数组或者指定个数的对象转换成一个List
集合。不能进行插入和删除操作,只能遍历。
五.Queue
接口
Queue
接口模拟队列这种特殊的数据结构,主要的方法如下:
add(),offer(),element(),peek(),poll(),remove()
1.LinkedList
实现类
LinkedList
类既可以当做双向队列来使用,也可以当做栈来使用,还可以当做List
集合来使用。
LinkedList
类与ArrayList
和Vector
类的实现机制完全不同,ArrayList
和Vector
类内部是以数组的形式保存元素,所以随机访问性能较好,而LinkedList
类是以链表的形式保存元素,所以随机访问性能较差,但是在迭代访问元素,插入、删除元素方面性能较好。
关于
List
集合实现类的选择问题:
· 如果需要遍历集合中的元素,对于ArrayList和Vector类最好使用随机访问(get())的方法,对于LinkedList类最好使用迭代器遍历。
· 如果需要经常执行插入和删除操作来改变集合的大小,则应该选用LinkedList类,而不要使用ArrayList类和Vector类。
· 如果需要多条线程同时访问List集合,则可以考虑使用Vector类来同步实现。
2.PriorityQueue
实现类
对于PriorityQueue
集合中的元素也是按照大小排序,排序的规则与TreeSet
类相同,也分自然排序和定制排序两种。
六.Map
接口
首先可以将Map
接口理解成一个特殊的Set
接口,只是该Set
接口中保存的元素都比较特殊,每个元素都是一个Entry
对象,Entry
类封装了一个key-value
对,它有三个方法:
·Object getKey()
·Object getValue()
·Object setValue(value)
其次也可以将Map
接口理解成一个特殊的List
接口,只是List
接口中用整数值做索引,而Map
接口中用key
值做索引,key
可以为任意对象。
Map
接口用于保存映射数据,它里面保存有两组数据,一组用来保存key
,一组用来保存value
。Key
不允许重复。Map
有时也被称为字典或者关联数组。
Map
接口提供的方法:
·添加元素:put(Object key,Object value),putAll(Map m)
·删除元素:remove(Object key)
·清除所有元素:clear()
·获取元素:get(Object key)
·测试:containsKey(key),containsValue(value),isEmpty()
·集合大小:size()
·转化:Collection values(),Set keyset(),Set entrySet()
1.HashMap
和Hashtable
类
HashMap
类和Hashtable
类的关系就像ArrayList
和Vector
类的关系一样。
HashMap
和Hashtable
类的区别:
·Hashtable
是一个线程安全类,而HashMap
不是线程安全的。但是HashMap
性能比Hashtable
性能高一些。
·Hashtable
不允许null
作为key
或者value
,而HashMap
允许。但在HashMap
集合中最多有一个key
为null
,但是可以有多个value
为null
。
HashMap
和Hashtable
类也不能保证其中key-value
对的顺序,但是它们中的key
必须实现equals
和hashCode
方法。
HashMap
和Hashtable
类判断两个key
值是否相等标准:通过equals
方法比较返回true
,并且具有相同的hashcode
。
HashMap
和Hashtable
类判断两个value
值是否相等标准:通过equals
方法比较返回true
。
与HashSet
类似,尽量不要使用可变对象作为HashMap
和Hashtable
的key
。
HashMap
的子类LinkedHashMap
:与HashMap
不同的是它可以维护元素的迭代顺序,在性能上略差于HashMap
,迭代速度却高于HashMap
。
Hashtable
的子类Properties
类:
Properties
类用来将Map
对象与属性文件关联起来,从而可以将Map
对象中的key-value
对加入到属性文件,同时也可以将属性文件中的内容加入到Map
对象中。
由于属性文件中的“属性名”和“属性值”都是字符串类型,所以Properties
文件中的key
和value
也都是字符串类型。
Properties
类主要提供如下几个方法:
·String getProperty(String key)
·String getProperty(String key,String defaultValues)
·void setProperty(String key,String value)
·void load(InputStream is)
·void store(OutputStream os,String comments)
3.SortedMap
接口和TreeMap
实现类
与SortedSet
接口和TreeMap
实现类完全类似。
4.WeakHashMap
实现类
WeakHashMap
类与HashMap
类基本相同,不同的是HashMap
的key
保留了对实际对象的强引用,而WeakHashMap
类的key
保留了对实际对象的弱引用。
5.IdentityHashMap
类
IdentityHashMap
类与HashMap
类基本相同,不同的是IdentityHashMap
类在判断key
值相等时,必须保证代表key
值的两个对象完全相等时才认为是相等的。
6.EnumMap
类
EnumMap
是一个与枚举类一起使用的Map
实现,它要求key
值必须是一个枚举类的枚举值,创建EnumMap
类时必须显示或者隐式的指定它对应的枚举类。
EnumMap
不允许使用null
作为key
值,但是允许null
作为value
值。
Map
集合的选择问题:
·
HashMap
和
Hashtable
类的效率基本相同,但
HashMap
的性能可能比
Hashtable
要好一些,因为
HashMap
没有实现同步操作。
·
TreeMap
类的性能不如
HashMap
,但是
TreeMap
类中的
key-value
对都是有序的。
·
LinkedHashMap
的性能比
HashMap
略差一点,因为它要维护
key
的插入顺序。
·
EnumMap
的性能最好,但是它要求必须要将一个枚举类中的元素作为
key
。
七.HashSet
和HashMap
的性能选项
桶:hash
表中可以存储元素的位置。
HashSet
和HashMap
的hash
表都有以下性能选项:
·容量(capacity
):hash
表中桶的数量
·初始化容量(initialCapacity
):创建hash
表时指定的桶的数量。
·尺寸(size
):当前散列表中记录的数量
·负载因子(loadFactor
):size/capacity
,轻负载的散列表具有冲突少,插入方便,易查询的优点。
负载极限:负载极限的值在0-1
之间,当超过负载极限时,会成倍的增加容量(rehashing
)。
八.操作集合的工具类Collections
Java
提供了一个操作Set
,List
,Map
等集合的工具类:Collections
。
1.
排序操作
Collections
提供了一下几个方法用于对List
集合进行排序(都是静态的):
·reverse(list)
:反转集合中的元素
·shuffle(list):
对集合中的元素进行随机排序
·sort(list)
:根据自然顺序对集合中的元素进行排序
·sort(list,comparator)
:根据定制顺序对集合中的元素进行排序
·swap(list,i,j)
:将i
和j
处的元素进行交换
·rotate(list,i):
将i
和list.length-1-i
处的元素进行交换
2.
查找、替换操作
Collections
提供了一下几个方法用于对List
集合进行查找、替换(都是静态的):
·binarySearch(list,object)
:查找指定元素在list
中的索引,但执行此方法前必须保证list
已经处于有序状态。
·max(collection):
按照自然排序查找collection
中的最大值
·max(collection,comparator):
按照定制排序查找collection
中的最大值
·min(collection):
按照自然排序查找collection
中的最小值
·min(collection,comparator): 按照定制排序查找collection中的最小值
·fill(list,object):
使用指定元素object
替换list
中的所有元素
·frequency(colletion,object):
返回集合collection
中object
元素出现的次数
·replaceAll(list,oldval,newval):
用新的元素newval
替代list
中所有旧的元素oldval
3.
同步控制
Collections
提供了多个synchronizedXxx
方法用来同步集合对象,可以解决多线程并发访问集合时的线程安全问题。
4.
设置不可变的集合
Collections
提供了三个方法返回一个不可变的集合:
·emptyXxx():
返回一个空的不可变的集合对象。
·singleton(object):
返回一个只包含一个元素object
的集合对象。
·unmodifiableXxx(colletion or map):返回一个不可变的视图。