一.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):返回一个不可变的视图。 |
|