声明:本文章经过别人文章摘要整理而来,并非纯原创作品!
- 集合框架
- 对于对象集合,必须执行的操作主要以下三种:
- 添加新的对象
- 删除对象
- 查找对象
- 对于对象集合,必须执行的操作主要以下三种:
- Collection(对象之间没有指定顺序,允许元素重复)
1)、List(有序、不唯一)
对象之间有指定顺序,允许元素重复,并引入位置下标
a、ArrayList (动态数组)
b、LinkedList(链表)
2)、Set(无序、唯一)
对象之间没有指定顺序,元素不能重复
a、HashSet(散列集合)
b、TreeSet(树集合)
c、SortedSet
2、Map(键值对、映射)
接口用于保存关键字(Key)和数值(Value)的集合,集合中的每个对象加入时都是提供
数值
和关键字。Map接口既不继承Set也不继承Collection。
1)、HashMap
2)、TreeMap
List、Set、Map、共同的实现基础是Object数组
- List(ArrayList、LinkedList)
List就是列表的意思,它是Collection 的一种,即继承了Collection接口,以定义一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。List是按对象的进入顺序进行保存对象,而不做排序或编辑操作。
它除了拥有Collection接口的所有的方法外还拥有一些其他的方法。
List:
简述 | 实现 | 操作特征 | 成员要求 |
提供基于索引的对成员的随机访问 | ArrayList | 提供快速的基于索引的成员访问,对尾部成员的增加和删除支持较好 | 成员可为任意Object子类的对象 |
LinkedList | 对列表中任何位置的成员的增加和删除支持较好,但对基于索引的成员访问支持性能较差 | 成员可为任意Object子类的对象 |
在“集合框架”中有两种常规的List实现:ArrayList和LinkedList。使用两种List实现的哪一种取决于您特定的需要。如果要支持随机访问,而不必在除尾部的任何位置插入或除去元素,那么,ArrayList提供了可选的集合。但如果,您要频繁的从列表的中间位置添加和除去元素,而只要顺序的访问列表元素,那么,LinkedList实现更好。
- Map
- HashMap
- LinkedHashMap
- TreeMap
Map接口不是Collection接口的继承
。而是从自己的用于维护键-值关联的接口层次结构入手。按定义,该接口描述了从不重复的键到值的映射。
这里需要注意的是,TreeMap中是根据键(Key)进行排序的。而如果我们要使用TreeMap来进行正常的排序的话,Key 中存放的对象必须实现
Comparable
接口。
Map | 简述 | 实现 | 操作特征 | 成员要求 |
保存键值对成员,基于键找值操作,使用compareTo或compare方法对键进行排序 | HashMap | 能满足用户对Map的通用需求 | 键成员可为任意Object子类的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。 | |
TreeMap | 支持对键有序地遍历,使用时建议先用HashMap增加和删除成员,最后从HashMap生成TreeMap;附加实现了SortedMap接口,支持子Map等要求顺序的操作 | 键成员要求实现Comparable接口,或者使用Comparator构造TreeMap键成员一般为同一类型 | ||
LinkedHashMap | 保留键的插入顺序,用equals 方法检查键和值的相等性 | 成员可为任意Object子类的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。 |
对于Map部分的使用和实现,主要就是需要注意存放“键值对”中的对象的
equals()
方法和
hashCode()
方法的覆写。如果需要使用到排序的话,那么还需要实现
Comparable
接口中的compareTo()方法。我们需要注意Map中的“键”是不能重复的,而是否重复的判断,是通过调用“键”对象的equals()方法来决定的。而在HashMap中查找和存取“键值对”是同时使用hashCode()方法和equals()方法来决定的。
HashMap的存入顺序和输出顺序无关。而LinkedHashMap则保留了键值对的存入顺序。TreeMap则是对Map中的元素进行排序。在实际的使用中我们也经常这样做:使用HashMap或者LinkedHashMap来存放元素,当所有的元素都存放完成后,如果使用则是需要一个经过排序的Map的话,我们再使用TreeMap来重构原来的Map对象。这样做的好处是:因为HashMap和LinkedHashMap存储数据的速度比直接使用TreeMap 要快,存取效率要高。当完成了所有的元素的存放后,我们再对整个的Map中的元素进行排序。这样可以提高整个程序的运行的效率,缩短执行时间。
- Set
- 概述:
Java 中的Set和正好和数学上直观的集(set)的概念是相同的。Set最大的特性就是不允许在其中存放的元素是重复的。根据这个特点,我们就可以使用Set 这个接口来实现前面提到的关于商品种类的存储需求。Set 可以被用来过滤在其他集合中存放的元素,从而得到一个没有包含重复新的集合。
Set | 简述 | 实现 | 操作特征 | 成员要求 | |
成员不能重复 | HashSet | 外部无序地遍历成员。 | 成员可为任意Object子类的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。 | ||
TreeSet | 外部有序地遍历成员;附加实现了SortedSet, 支持子集等要求顺序的操作 | 成员要求实现Comparable接口,或者使用Comparator构造TreeSet。成员一般为同一类型。 | |||
LinkedHashSet | 外部按成员的插入顺序遍历成员 | 成员与HashSet成员类似 |
排序:
Set sortedSet = new
TreeSet(set1);
System.out.println("排序后 TreeSet :"
+
sortedSet
);
HashSet的元素存放顺序和我们添加进去时候的顺序没有任何关系,而LinkedHashSet 则保持元素的添加顺序。TreeSet则是对我们的Set中的元素进行排序存放。
- 迭代器Iterator
Collection接口的iterator()方法返回一个Iterator。Iterator和您可能已经熟悉的Enumeration接口类似。使用 Iterator接口方法,您可以从头至尾遍历集合,并安全的从底层Collection中除去元素。
ListIterator接口继承Iterator接口以支持添加或更改底层集合中的元素,还支持双向访问
。
以HashSet举例:
Set set1 =
new
HashSet();
Iterator iterator =set1.iterator();
//得到一个迭代器
while
(
iterator.hasNext()
) {
//遍历
Object element =iterator.next();
System.out.println("iterator = "
+ element);
}
- 集合框架中常用类比较
用“集合框架”设计软件时,记住该框架四个基本接口的下列层次结构关系会有用处:
- Collection 接口是一组允许重复的对象。
- Set 接口继承 Collection,但不允许重复。
- List 接口继承 Collection,允许重复,并引入位置下标。
- Map 接口既不继承 Set 也不继承 Collection,存取的是键值对
我们以下面这个图表来描述一下常用的集合的实现类之间的区别:
- 排序
Comparable 接口
compareTo()方法比较当前实例和作为参数传入的元素。如果排序过程中当前实例出现在参数前,就返回某个负值。如果当前实例出现在参数后,则返回正值。否则,返回零。这里不要求零返回值表示元素相等。零返回值只是表示两个对象排在同一个位置。
在 Java 2 SDK,版本 1.2 中有十四个类实现Comparable接口。下表展示了它们的自然排序。虽然一些类共享同一种自然排序,但只有相互可比的类才能排序。
创建您自己的类Comparable只是个实现compareTo()方法的问题。通常就是依赖几个数据成员的自然排序。
您自己的类也应该覆盖equals()和hashCode()以确保两个相等的对象返回同一个散列码
。
Comparator 接口
若一个类不能用于实现 java.lang.Comparable,您可以提供自己的 java.util.Comparator 行为。如果您不喜欢缺省的Comparable 行为,您照样可以提供自己的 Comparator。
Comparator 的 compare() 方法的返回值和 Comparable 的 compareTo() 方法的返回值相似。在此情况下,如果排序时第一个元素出现在第二个元素之前,则返回一个负值。如果第一个元素出现在后,那么返回一个正值。否则,返回零。与 Comparable 相似,零返回值不表示元素相等。一个零返回值只是表示两个对象排在同一位置。由Comparator 用户决定如何处理。如果两个不相等的元素比较的结果为零,您首先应该确信那就是您要的结果,然后记录行为。
为了演示,您会发现编写一个新的忽略大小写的 Comparator,代替使用 Collator 进行语言环境特定、忽略大小写的比较会更容易。这样的一种实现如下所示:
classCaseInsensitiveComparator implements Comparator {
public int compare(Object element1, Objectelement2) {
String lowerE1 =((String)element1).toLowerCase();
String lowerE2 =((String)element2).toLowerCase();
return lowerE1.compareTo(lowerE2);
}
}
因为每个类在某些地方都建立了 Object 子类,所以这不是您实现 equals() 方法的必要条件。实际上大多数情况下您不会去这样做。切记该 equals() 方法检查的是 Comparator 实现的等同性,不是处于比较状态下的对象。
Collections 类有个预定义的 Comparator 用于重用。调用 Collections.reverseOrder() 返回一个 Comparator,它对逆序实现 Comparable 接口的对象进行排序。
在JAVA的util包中有两个所有集合的父接口Collection和Map,它们的父子关系:
java.util
+Collection
这个接口extends自 --java.lang.Iterable接口
+List
接口
-ArrayList
类
-LinkedList
类
-Vector
类 此类是实现同步的
+Queue
接口
+
不常用,在此不表.
+Set
接口
+SortedSet
接口
-TreeSet
类
-HashSet
+Map
接口
-HashMap
类 (除了不同步和允许使用null 键/值之外,与 Hashtable 大致相同.)
-Hashtable
类此类是实现同步的,不允许使用null 键值
+SortedMap
接口
-TreeMap
类
以下对众多接口和类的简单说明:首先不能不先说一下数组(Array)
一、Array , Arrays
Java所有“存储及随机访问一连串对象”的做法,array是最有效率的一种。
1、
效率高,但容量固定且无法动态改变。
array还有一个缺点是,无法判断其中实际存有多少元素,length只是告诉我们array的容量。
2、Java中有一个Arrays类,专门用来操作array。
arrays
中拥有一组static函数,
equals():比较两个array是否相等。array拥有相同元素个数,且所有对应元素两两相等。
fill():将值填入array中。
sort():用来对array进行排序。
binarySearch():在排好序的array中寻找元素。
System.arraycopy():array的复制。
二、Collection , Map
若撰写程序时不知道究竟需要多少对象,需要在空间不足时自动扩增容量,则需要使用容器类库,array不适用。
1、Collection 和 Map 的区别
容器内每个为之所存储的元素个数不同。
Collection类型者,每个位置只有一个元素。
Map类型者,持有key-value pair,像个小型数据库。
2、Java2容器类类库的用途是“保存对象”,它分为两类,各自旗下的子类关系
Collection
--
List
:
将以特定次序存储元素。所以取出来的顺序可能和放入顺序不同
。
--ArrayList/ LinkedList / Vector
--
Set
:不能含有重复的元素
--HashSet/TreeSet
Map
--HashMap
--
HashTable
--
TreeMap
Map----一组成对的“键值对”对象,即其元素是成对的对象,最典型的应用就是数据字典,并且还有其它广泛的应用。另外,Map可以返回其所有键组成的Set和其所有值组成的Collection,或其键值对组成的Set,并且还可以像数组一样扩展多维Map,只要让Map中键值对的每个“值”是一个Map即可。
Collection下
1.迭代器
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
Java中的Iterator功能比较简单,并且只能单向移动:
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。
注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
2.List的功能方法
List(interface):
次序是List最重要的特点;它确保维护元素特定的顺序。List为Collection添加了许多方法,使得能够向List中间插入与移除元素(只推荐LinkedList使用)。一个List可以生成ListIterator,使用它可以从两个方向遍历List,也可以从List中间插入和删除元素。
ArrayList:
由数组实现的List。它允许对元素进行快速随机访问,但是向List中间插入与移除元素的速度很慢。
ListIterator只应该用来由后向前遍历ArrayList
,而不是用来插入和删除元素,因为这比LinkedList开销要大很多。
LinkedList:
由列表实现的List。对顺序访问进行了优化,向List中间插入与删除得开销不大,随机访问则相对较慢(可用ArrayList代替)。它具有方法a
ddFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()
,这些方法(没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。
3.Set的功能方法
Set(interface):
存入Set的每个元素必须是唯一的
,这也是与List不同的,因为Set不保存重复元素。
加入Set的Object必须定义equals()方法以确保对象的唯一性。
Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。
HashSet:HashSet
能快速定位一个元素,
存入HashSet的对象必须定义hashCode()。
TreeSet
:保持次序的Set,底层为树结构。使用它可以从Set中提取有序的序列。
LinkedHashSet
:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。
HashSet采用散列函数对元素进行排序,这是
专门为快速查询而设计的
;TreeSet采用红黑树的数据结构进行排序元素;LinkedHashSet内部使用散列以加快查询速度,同时使用链表维护元素的次序,使得看起来元素是以插入的顺序保存的。需要注意的是,生成自己的类时,Set需要维护元素的存储顺序,因此要实现Comparable接口并定义compareTo()方法。
3、其他特征
* List,Set,Map将持有对象一律视为Object型别。
* Collection、List、Set、Map都是接口,不能实例化。
继承自它们的 ArrayList, Vector, HashTable, HashMap是具象class,这些才可被实例化。
* vector容器确切知道它所持有的对象隶属什么型别。vector不进行边界检查。
三、Collections
Collections是针对集合类的一个帮助类。
提供了一系列
静态
方法实现对各种集合的搜索、排序、线程完全化等操作。
相当于对Array进行类似操作的类——Arrays。
如,
Collections.max(Collectioncoll); 取coll中最大的元素。
Collections.sort(List list);
对list中元素排序
四、如何选择?
1、容器类和Array的区别、择取
*
容器类仅能持有对象引用(指向对象的指针),而不是将对象信息copy一份至数列某位置。
*
一旦将对象置入容器内,便损失了该对象的型别信息。
2、
*
在各种Lists中,最好的做法是以ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList();
Vector
总是比ArrayList慢,所以要尽量避免使用。
*
在各种Sets中,HashSet通常优于HashTree(插入、查找)。只有当需要产生一个经过排序的序列,才用TreeSet。
HashTree
存在的唯一理由:能够维护其内元素的排序状态。
*
在各种Maps中
HashMap
用于快速查找。
*
当元素个数固定,用Array,因为Array效率是最高的。
结论:最常用的是ArrayList,HashSet,HashMap,Array。而且,我们也会发现一个规律,用TreeXXX都是排序的。
注意:
1、Collection没有get()方法来取得某个元素。只能通过iterator()遍历元素。
2、Set和Collection拥有一模一样的接口。
3、
List
,
可以通过get()方法来一次取出一个元素
。使用数字来选择一堆对象中的一个,get(0)...。(add/get)
4、一般使用ArrayList。
用LinkedList构造堆栈stack、队列queue
。
5、
Map用 put(k,v) / get(k)
,还可以使用containsKey()/containsValue()来检查其中是否含有某个key/value。
HashMap
会利用对象的hashCode来快速找到key。
* hashing
哈希码就是将对象的信息经过一些转变形成一个独一无二的int值,这个值存储在一个array中。
我们都知道所有存储结构中,array查找速度是最快的。所以,可以加速查找。
发生碰撞时,让array指向多个values。即,数组每个位置上又生成一个梿表。
6、Map中元素,可以将key序列、value序列单独抽取出来。
使用
keySet()
抽取key序列,将map中的所有keys生成一个Set。
使用
values(
)
抽取value序列,将map中的所有values生成一个Collection。
为什么一个生成Set,一个生成Collection?那是因为,key总是独一无二的,value允许重复。