Java OOP——第六章 框架集合
1、集合框架包含的主要内容及彼此之间的关系:
图1: |
![]() |
集合框架:是为了表示和操作集合而统一规定的一种统一的标准体系结构。 包含三大块的内容:对外的接口、接口的是实现和对集合运算的算法; Java集合框架提供了一套性能优良、使用方便的接口和类,它们位于java.util包中: ●接口:表示集合的抽象数据类型,在图1中用虚线框表示,下图绿色的: ●实现:集合框架中接口的具体实现,图1中一实线表示,粗实线表示常用的:上图蓝色的: ●算法:在一个实现了某个集合框架中的接口的对象身上完成某种有用的计算的方法;如:查询、排序; Java提供了进行集合操作的工具类Collections(类似于Arrays类):它提供了对集合进行排序、遍历等多种算法实现; |
2、java集合中的的两大类接口:Collection和Map;
●Collection:Collection 接口存储一组不唯一,无序的对象(List:不唯一、有序;Set:唯一、无序;所以Collection接口是不唯一无序的);
●List:List 接口继承Collection 接口,存储一组不唯一(允许重复),有序(以插入的次序来放置元素,不会重写排列)的对象;
●Set:Set 接口继承Collection 接口,存储一组唯一(不允许重复),无序的对象;
●Map:Map接口存储一组键值对象,提供key到value的映射,Map中的Key不要求有序、不允许重复。value同样不要求有序,但允许重复;
●Iterator(迭代器):接口是负责定义访问和遍历元素的接口;、
3、List接口:常用的类:ArrayList和LinkedList;(附加: Vector类:Vector集合类的使用(线程安全具有同步性),Stack类)
●ArrayList集合类对数组进行了封装,实现了长度可变的数组,存储数据的方式和数组相同,都是在内存中分配连续的空间;
优点:在内存中分配连续的空间。遍历元素和随机访问元素的效率比较高;
缺点:ArrayList类的使用无同步性,线程不安全;
●使用ArrayList存储元素: ●使用ArrayList移除、判断元素: |
|||
Eg:ArrayList集合的增删查: |
|||
Pet类(父类): |
Dog类(子类):
|
||
Test测试类: |
遍历方式1:(for) 遍历方式2:(foreach) |
||
添加元素: |
按指定位置添加元素: |
||
上面的代码的输出结果: |
|
||
删除元素(按索引删除): 结果:(与上面进行对比) |
删除元素(按对象删除): 结果(与上面进行对比): |
||
判断对象是否存在: |
输出结果: |
●List接口(ArrayList)常用方法:
方法名 |
说 明 |
boolean add(Object o) |
在列表的末尾顺序添加元素,起始索引位置从0开始 |
void add(int index,Object o) |
在指定的索引位置添加元素。原索引位置及其后面的元素依次后移; 注意:新添加元素的索引位置必须介于0和列表中元素个数之间; |
int size() |
返回列表中的元素个数 |
Object get(int index) |
返回指定索引位置处的元素。 注意:取出的元素是Object类型,使用前需要进行强制类型转换 |
boolean contains(Object o) |
判断列表中是否存在指定元素 |
boolean remove(Object o) |
从列表中删除元素 |
Object remove(int index) |
从列表中删除指定位置元素,起始索引位置从0开始 |
●附加: ArrayList和Vector的区别:
相同点:ArrayList与Vector都是java的集合类,都可以用来存放java对象 |
不同点(如下): |
1、同步性: Vector是线程同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。 ArrayList则是线程异步的,因此ArrayList中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销。 |
2、数据增长: 从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。 |
●LinkedList采用链表存储方式。它提供了额外的addFirst(),addLast(),removeFirst()和removeLast()等方法;这些方法使得该集合可被当作堆栈(stack)或列(queue)
优点:插入、删除元素时效率比较高;
● 使用LinkedList存储元素: |
|
Test测试类:(父类和子类见上面集合): |
添加元素方式1: 添加元素方法2: |
遍历元素: 输出结果: |
访问指定对象: 结果: |
删除指定对象: 结果: |
删除指定对象2: 结果: |
●LinkedList的特殊方法:
方法名 |
说 明 |
void addFirst(Object o) |
在列表的首部添加元素 |
void addLast(Object o) |
在列表的末尾添加元素 |
Object getFirst() |
返回列表中的第一个元素 |
Object getLast() |
返回列表中的最后一个元素 |
Object removeFirst() |
删除并返回列表中的第一个元素 |
Object removeLast() |
删除并返回列表中的最后一个元素 |
4、Map接口:Map接口存储一组键值对象,提供key到value的映射,Map中的Key不要求有序、不允许重复。value同样不要求有序,但允许重复;
●HashMap集合类:
●使用HashMap存储元素: |
|
Test测试类:(父类和子类见上面集合): |
添加元素方式1: 通过key获得值: |
获得元素的个数: 结果: |
判断key是否存在: 结果: |
判断key是否存在: 结果: |
判断值是否存在: 结果: |
删除指定元素: 清空元素: 结果: |
显示键值集合数据: 输出结果: |
循环遍历key: 结果: |
循环遍历值: 结果: |
●Map接口常用方法:
方法名 |
说 明 |
Object put(Object key, Object val) |
以“键-值对”的方式进行存储 注意:键必须是唯一的,值可以重复,如果试图添加重复的键,加入的键值对会替换原来的 |
Object get (Object key) |
根据键返回相关联的值,如果不存在指定的键,返回null |
Object remove (Object key) |
删除由指定的键映射的“键-值对” |
int size() |
返回元素个数(返回此映射中的键-值映射关系数。) |
Set keySet () |
返回键的集合 |
Collection values () |
返回值的集合 |
boolean containsKey (Object key) |
如果存在由指定的键映射的“键-值对”,返回true |
Boolean isEmpty() |
若不存在键值对关系,则返回true |
void clear() |
从此映射中移除所有映射关系; |
- ●Hashtable集合类:Hashtable集合类的使用(Hashtable具有同步性,线程安全);
- ●HashMap和Hashtable集合类对比:
HashMap和Hashtable的异同: ◆HashMap类出现之前,JDK中存在一个和它 同样采用哈希表存储方式。同样实现键值映射的集合类,HashMap,两者实现原理相同,功能相同,很多情况下可以互用; |
|
HashMap和Hashtable的主要区别: ◆Hashtable继承自Dictionary类,而HashMap是实现了Map接口,(是java 1.2引进的Map接口的一个实现。) ◆Hashtable是线程安全的,HashMap重速度轻安全,是线程非安全,所以当运行到多线程环境中时,需要程序员自己管理线程的同步问题; ◆HashMap可以让你将空值作为一个表的条目的key或value但是Hashtable是不能放入空值的(null); ◆同步性:Hashtable是线程同步的。这个类中的一些方法保证了Hashtable中的对象是线程安全的。 HashMap则是线程异步的,因此HashMap中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用HashMap是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销,从而提高效率。 |
|
![]() |
![]() |
注意: 开发过程中,最好使用ArrayList和HashMap; |
5、迭代器(Iterator):
●java.util包中包含了一系列重要的集合类,集合类的根接口Collection。Collection接口是所有集合类的根类型。
●通过迭代器Iterator实现遍历:
●获取Iterator :Collection 接口的iterator()方法
●Iterator的方法
●boolean hasNext(): 判断是否存在另一个可访问的元素
●Object next(): 返回要访问的下一个元素
★附加:每一种集合类返回的Iterator具体类型可能不同,Array可能返回ArrayIterator,Set可能返回SetIterator,Tree 可能返回TreeIterator,但是它们都实现了Iterator接口,因此,客户端不关心到底是哪种Iterator,它只需要获得这个 Iterator接口即可,
6、遍历Map集合的方法:
●方法1:通过迭代器Iterator实现遍历 |
●方法2:增强for循环 |
Test测试类: |
向HashMap中添加元素: 遍历方式2:(增强for): 输出结果: |
遍历方式1:(迭代器) |
输出结果: |
7、数组和集合的区别:
●数组可以存储基本数据类型和对象,而集合中只能存储对象(可以以包装类形式存储基本数据类型) ●数组长度固定。集合长度可以动态改变; ●定义数组时必须指定数组元素类型,集合默认其中所有元素都是Object ●无法直接获取数组实际存储的元素个数,length用来获取数组的长度,但可以通过size()方法直接获取集合实际存储的元素个数; ●集合有很多种实现方式和不用的使用场合,而不像数组仅分配连续空间方式; ●集合以接口和类的形式存在,具有封装、继承和多态等类的特性,通过简单的方法和属性调用即可实现各种复杂操作,大大提高了软件的开发效率; ●JDK中 有一个Arrays类,专门用来操作数组,它提供了一系列静态方法实现,对数组搜索、排序、比较和填充等操作。 JDK中有一个Collections类,专门用来操作集合,它提供一系列静态方法实现对各种集合的搜索、复制、排序和线程安全化等操作; |
8、泛型(Generic)集合:
●泛型是java se1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
●在java se1.5之前,没有泛型的情况下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的,对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
●使用泛型有下面几个优点:
1、类型安全
2、向后兼容(泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率)
3、层次清晰
4、性能较高,用GJ(泛型JAVA)编写的代码可以为java编译器和虚拟机带来更多的类型信息,这些信息对java程序做进一步优化提供条件。
Eg:ArrayList:
|
Eg:Map和Set: |
|
List泛型集合: |
||
Test测试类: |
添加元素:(向狗中添加企鹅会编译错误): |
|
移除指定元素: |
|
|
Map: |
||
Test测试类: |
添加元素:(向狗中添加企鹅会编译错误): |
|
遍历: |
|
9、如何选用集合类?
1、要求线程安全,使用Vector、Hashtable
2、不要求线程安全,使用ArrayList,LinkedList,HashMap
3、要求key和value键值,则使用HashMap,Hashtable
4、数据量很大,又要线程安全,则使用Vector
10、附加:
●Java中的Iterator(迭代器)的用法:
◆它的一个主要的接口方法是:
●boolean add(Object c)添加数据:add()方法将添加一个新元素。注意这个方法会返回一个boolean,但是返回值不是表示添加成功与否。
●Collection规定:如果一个集合拒绝添加这个元素,无论任何原因,都必须抛出异常。
这个返回值表示的意义是add()方法执行后,集合的内容是否改变了(就是元素有无数量,位置等变化),这是由具体类实现的。即:如果方法出错,总会抛出异常;返回值仅仅表示该方法执行后这个Collection的内容有无变化。
▲类似还有:
boolean addall(Collection c);添加所有数据
boolean remove(Object o);删除数据
boolean removeall(Collection c);删除所有数据
boolean remainall(Collection c);保持所有数据
★Object[]toArray()方法很简单,把集合转换成数组返回。Object[]toArray(Object[] a)方法就有点复杂了,首先,返回的Object[]仍然是把集合的所有元素变成数组,但是类型和参数a的类型是相同的。
如:String[] o=(String)c.toArray(new String[0]); //得到的o实际类型是String[]数组。
●其次,如果参数a的大小装不下集合的所有元素,返回的将是一个新的数组。如果参数a的大小能装下集合的所有元素,则返回的还是a,但a的内容用集合的元素来填充。
尤其要注意的是,如果a的大小比集合元素的个数还多,a后面的部分全部被置为null(空)。
●Set结构的集合类:HashSet类,TreeSet类
◆HashSet是基于HashMap实现的,HashSet底层采用HashMap来保存所有元素。hashCode和equal()是HashMap用的,因为无需排序所以只需要关注定位和唯一性即可;hashCode是用来计算hash值的,hash值是用来确定hash表索引的,hash表中的一个索引存放的是一张链表,所以还要通过equal方法循环比较链上的每一个对象才可以真正定位到键值对应的Entryput时,如果hash表中没定定位到,就在链表前加一个Entry,如果定位到了,则更换Entry中的value(值)并返回value(值)
◆覆写key的hashCode()和equal()时一定要注意,不要把它们和可变属性关联上,否则属性变了之后hashCode会变,equal也会为false,这样在Map中就找不到它了而且这样的对象因为找不到它所以得不到释放,这样就变成了一个无效引用(相当于内存泄漏)
◆TreeSet集合类是一个有序集合,它的元素按照升序排序,默认是自然顺序排列,也就是说TreeSet中的对象元素需要实现Comparable接口。TreeSet与HashSet类一样没有get()方法来获取列表中的元素,所以也只能通过迭代器方法来获取。由于TreeMap需要排序,所以需要一个Comparator为键值进行大小比较,当然也是用Comparator定位的Comparator可以在创建TreeMap时指定,这时排序时使用Comparator.compare如果创建时没有指定Comparator那么就会使用key.compareTo()方法,这就要求key必须实现Comparable接口
◆TreeMap是使用Tree数据结构实现的,所以使用compare接口就可以完成定位了。TreeSet是依靠TreeMap来实现的,TreeSet是一个有序集合,它的元素按照升序排列,默认是按照自然顺序排列,也就是说TreeSet中的对象元素需要实现Comparable接口。TreeSet类中跟HashSet类一要也没有get()方法来获取列表中的元素,所以也只能通过迭代器的方法来获取 。
◆HashSet与TreeSet集合类的区别:HashSet是基于hash算法实现的,性能优于TreeSet。通常使用HashSet,在我们需要对其中元素排序的时候才使用TreeSet。
●Java中的List/Set和Map的区别:
★List按对象进入的顺序保存对象,不做排序和编辑操作。
★Set对每个对象只接受一次,并使用自己内部的排序方法(通常,你只关心某个元素是否属于Set而不关心它的顺序--否则使用List)。
★Map同样对每个元素保存一份,但这是基于"键"(key)的,Map也有内置的排序,因而不关心元素添加的顺序。如果添加元素的顺序对程序设计很重要,应该使用LinkedHashSet或者LinkedHashMap。
●List的功能方法:
实际上有两种List:一种是基本的ArrayList其优点在于随机访问元素,另一种是更强大的LinkedList它并不是为快速随机访问设计的,而是具有一套更通用的方法。
★List:次序是List最重要的特点:它保证维护元素特定的顺序。List为Collection添加了许多方法,使得能够向List中间插入与移除元素(这只推荐LinkedList使用)一个List可以生成Listlterator,使用它可以从两个方向遍历List,也可以从List中间插入和移除元素。
★ArrayList:由数组实现的List。允许对元素进行快速随机访问,但是向List中间插入与移除元素的速率很慢。Listlterator只应该用来由后向前遍历ArrayList。而不是用来插入和移除元素。因为那比LinkedList开销要大很多。
★LinkedList:对顺序访问进行了优化,向List中间插入与删除的开销并不大。随机访问则相对较慢。
(使用ArrayList代替)还具有下列方法:addFirst(),addLast(),getFirst(),getLast(),removeFirst()和removeLast()
这些方法(没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。
●Set的功能方法:
★ Set具有与Collection完全一样的接口,因此没有任何额外的功能,不象前面有两个不同的List。
实际上Set就是Collection,只是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素(至于如何判断元素相同则较为负责)
★ Set:存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必需定义equals()方法以确保对象的唯一性。
Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。
★ HashSet:为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。
★ TreeSet:保存次序的Set,底层为树结构。使用它可以从Set中提取有序的序列。
★ LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。
●Map的功能方法:
★方法put(Object key,Object value)添加一个"值"(想要得东西)和与"值"相关的"键"(key)(使用它来查找)。
★方法get(Object key)返回与给定"键"相关联的"值"。可以用containsKey()和containsValue()测试Map中是否包含某个"键"或"值"。标准的java类库中包含了几种不同的Map:HashMap,TreeMap,LinkedHashMap,WeakHashMap,ldentityHashMap。们都有同样的基本接口Map,但是行为、效率、排序策略、保存对象的生命周期和判定"键"等价的策略等各不相同。
★ 执行效率是Map的一个大问题。看看get()要做哪些事,就会明白为什么在ArrayList中搜索"键"是相当慢的。这正是HashMap提高速度的地方。HashMap使用了特殊的值,称为"散列码"(hash code),来取代对键的缓慢搜索。"散列码"是"相对唯一"用以代表对象的int值,它是通过将该对象的某些信息进行转换而生成的。所有java对象都能产生散列码,因为hashCode()是定义在基类Object中的方法。
★ HashMap就是使用对象的hashCode()进行快速查询的。此方法能够显著提高性能。
▲Map:维护"键值对"的关联性,使你可通过"键"查找"值"
▲ HashMap:Map基于散列表的实现。插入和查询"键值对"的开销是固定的。可以通过构造器设置容量capacity和负载因子load factor,以调整容器的性能。
▲ LinkedHashMap:类似于HashMap,但是迭代遍历它时,取得"键值对"的顺序是其插入次序,或者是最近最少使(LRU)的次序。
只能HashMap慢一点。而在迭代访问时发而更快,因为它使用键表维护内部次序。
▲TreeMap:基于红黑树数据结果的实现。查看"键"或"键值对"时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在于,
你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。
▲ WeakHashMap:旨键(weak key)Map,Map中使用的对象也被允许释放:这是为解决特殊问题设计的。如果没有map之外的引用指向某个"键",则此"键"可以被垃圾收集器回收。
▲ ldentifyHashMap:使用==代替equals()对"键"作比较的hash map。专为解决特殊问题而设计。
11、附加2:
●Java中Collections类完全由在 collection 上进行操作或返回 collection 的静态方法组成。 它包含在 collection 上操作的多态算法,即“包装器”,包装器返回由指定 collection 支持的新 collection,以及少数其他内容。 binarySearch()方法提供了多种重载形式,用于满足各种类型数组的查找需要, binarySearch()有两种参数类型此法为二分搜索法(使用二分搜索法搜索指定列表), 故查询前需要用sort()方法将数组排序,如果数组没有排序,则结果是不确定的,另外如果数组中含有多个指定值的元素,则无法保证找到的是哪一个。 |
|||||
●Collection和Map其中Collection接口又有众多子接口,其中常用的有:List和Set,还有一些不常用的比如:Queue,Deque,NavigableSet,BeanContext,BeanContextServices,BlockingDeque,SortedSet |
|||||
●List和Set都是单列元素的集合,它们有一个共同的父接口Collection。 List内的元素讲究有序性,内部元素可重复;但是Set恰恰相反,它讲究的是无序性,元素不可重复。 Map与List和Set不同,它是双列存储的(键和值一一对应) |
|||||
●HashSet的存储方式:散列存储; |
|||||
●在Java集合框架中,有些类是线程同步安全的类,它们是Vector、Hashtable、Stack、enumeration。 除了这些之外,其他的都是非线程安全的类和接口。 线程安全类的方法是同步的,每次只能一个访问,它们是重量级对象,效率较低。 对于非线程安全的类和接口,在多线程中需要程序员自己处理线程安全问题 |
|||||
●Java中的集合包括三大类,它们是Set、List和Map, 它们都处于java.util包中,Set、List和Map都是接口,它们有各自的实现类。 Set接口,无重无序; List接口允重有序,正好相反!Map接口包含键值对,值重键不重。 |
|||||
●Collections类的常用方法: java.util.Collections类包含很多有用的方法,可以使程序员的工作变得更加容易。常用方法有: 1) 使用sort()方法可以根据元素的自然顺序 对指定列表按升序进行排序。 列表中的所有元素都必须实现 Comparable 接口。此列表内的所有元素都必须是使用指定比较器可相互比较的。 2) 使用shuffle()混排算法所做的正好与 sort 相反。它打乱在一个 List 中可能有的任何排列的踪迹。 也就是说,基于随机源的输入重排该 List, 这样的排列具有相同的可能性(假设随机源是公正的)。 3)使用reverse()方法可以根据元素的自然顺序,对指定列表按降序进行排序。 4)使用swap()方法可以在指定列表的指定位置处交换元素。 |
|||||
●HashSet是Set接口的实现类,HashMap类是Map接口的实现类。ArrayList实现了长度可变的数组,在内存中分配连续的空间。LinkedList采用链表存储方式。TreeSet是Set接口的实现类,TreeMap类是Map接口的实现类。 |
|||||
●Collection类的常用方法: containsAll(Collection c)方法为判断是否包含指定 collection 中的所有元素。 Remove(Object obj)方法为移除集合中某个元素。 注意:compareTO(Object obj)方法是在Comparable接口中定义的。 |
|||||
●Java中Collections类完全由在 collection 上进行操作或返回 collection 的静态方法组成。 它包含在 collection 上操作的多态算法,即“包装器”,包装器返回由指定 collection 支持的新 collection,以及少数其他内容。 因为Collections类提供的方法都是static的,所以可以直接调用执行,不需实例化对象。 |
|||||
●ArrayList类的常用方法。boolean add(E e) 该方法是将指定的元素添加到此列表的尾部。里面元素可以重复. hashMap里面键一样的才会被覆盖; |
|||||
●Java中,ArrayList提供了三种方式的构造器: 可以构造一个默认初始容量为10的空列表、构造一个指定初始容量的空列表,以及构造一个包含指定collection的元素的列表, 这些元素按照该collection的迭代器返回它们的顺序排列的。 Eg:List al=new ArrayList(100);将会创建一个预计有100个元素的ArrayList对象a1; |
|||||
●Java的ArrayList类是传说中的动态数组,它实现了ICollection和IList接口,可以动态的增加和减少元素、灵活的设置数组的大小。 ArrayList类的add()方法用于添加一个元素到当前列表的末尾。 |
|||||
Eg: |
分析: Java 的ArrayList类有很多方法。 选项B的代码中ArrayList使用toArray()方法将list对象转为Object[]数组对象,但执行System.out.println(list.toArray())方法不能输出展示list对象中的全部数据; 选项D的代码利用get(int index)方法获得指定索引位置的数据,并调用的System.out.println()方法输出该数据。 注意:本题要求打印出list中储存的所有数据,不是指定的某个索引位置的数据。 因此,选项D的打印输出结果不符合本题要求。本题应选择AC。
|
||||
Eg: |
分析: ArrayList集合中: 进行元素替换可使用set(int arg,Object o)的方法,set方法中俩个参数,第一个i是修改下标,第二个参数是修改的值。 也可以通过移除remove(int index)或者remov(Object o),然后添加add(Obeject o)的方式。remove()方法重载参数可以填值或者下标来移除元素,D项add()方法重载中一时添加的下标,2是添加的value值。 故BD可以实现修改修改元素 |
||||
Eg: |
分析: peek()方法是返回但不删除第一个元素, remove()方法是 返回并且删除第一个元素, 所以调用这两个方法后 ,列表中的值是“橙黄绿”答案C |
||||
●ArrayList,是可以改变大小的,我们称之为容量capacity在ArrayList存储成员达到增大的阀值时,会自动增加大小,其不指定时,默认大小为10。ArrayList不仅可以存储null值,同时也可以存储重复的值。 |
|||||
●Java的ArrayList类是传说中的动态数组,它实现了ICollection和IList接口,可以动态的增加和减少元素、灵活的设置数组的大小。 ArrayList类的add()方法用于添加一个元素到当前列表的末尾,get()方法则是按照int类型的索引(从0开始计数)返回此列表中指定位置上的元素。 |
|||||
●LinkedList是实现List、Collection接口,是链表方式进行构建的,根据开发要求不同,可以使用LinkedList实现栈(先进先出)和堆(先进后出)这样的数据结构。 |
|||||
●Java集合框架中,LinkedList类实现所有可选的列表操作,并且允许所有元素(包括 null)。 LinkedList常用方法:offer()是将指定元素添加到此列表的末尾(最后一个元素); pop()方法从此列表所表示的堆栈处弹出一个元素,即移除并返回此列表的第一个元素; offerFirst()方法是在此列表的开头插入指定的元素; get()方法是返回此列表中指定位置处的元素。本题应选择C。 注意:与offerFirst()方法对应的offerList()方法则是在此列表末尾插入指定的元素。 |
|||||
Eg: |
分析: 该题使用HashMap存储诗人信息,主要考察的是HashMap的常用方法 1.Object map.get(Object key) 获得与key(李白)相关的value(唐代大诗人) 2.boolean containsKey(Object key) 判断map集合中是否存在key(李白):true 3.boolean containsValue(Object value) 判断map集合中是否存在value(台湾著名作家):true 4.int size() 返回集合中元素的数量:2 5.boolean isEmpty 判断集合中是否存在元素(为空返回true,存在元素返回false): |
||||
Eg:
|
分析: 本题要从hMap中查找得到value是“Oracle”的字符串,要通过与之对应的key值"3"才能得到。 注意:put方法添加对象时key的值是字符串"1"、"2"、"3"、"4",选项C的代码hMap.get(3)中参数是整数类型,而不是字符串"3", Java的HashMap是Java Collection Framework 的重要成员,是 Map 接口的常用实现类。 对HashMap 而言,系统将 key-value 当成一个整体进行处理,根据 Hash 算法来计算 key-value 的存储位置,这样可以保证能快速存、取 Map 的 key-value 对。 HashMap 采用一种所谓的“Hash 算法”来决定每个元素的存储位置。 当需要向HaspMap中添加对象时,程序执行该类的put()方法,系统将调用key值的 hashCode() 方法得到其 hashCode 值。得到这个对象的 hashCode 值之后,系统会根据该 hashCode 值来决定该元素的存储位置。 而要获取HaspMap中某个对象时,程序调用get()方法通过 key 取出对应 value 时,系统只要先计算出该 key 的 hashCode() 返回值,在根据该 hashCode 返回值找出该 key 在 table 数组中的索引,然后取出该索引处的 Entry,最后返回该 key 对应的 value 即可。 |
||||
●HashMap类是基于哈希表的 Map 接口的实现。它提供所有可选的映射操作,并允许使用 null 值和 null 键。但此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 |
|||||
●HashMap 类是一个散列表,它存储的内容是键值对(key-value)映射。 HashMap 继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。 因为它属于Map接口的类,所以实现了将唯一键映射到特定的值上。 同时,它的key、value都可以为null。所以,HashMap对象中最多只有1个key值可以为null。 |
|||||
●Map将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值,在Java中Key的值重复,会默认覆盖前一个。在C#会报错。 |
|||||
●HashMap类和Hashtable类都是基于哈希表的 Map 接口的实现。 Java集合框架中,有些类是线程同步安全的类,它们是Vector、Hashtable、Stack、enumeration。除了这些之外,其他的都是非线程安全的类和接口。 线程安全类的方法是同步的,每次只能一个访问,它们是重量级对象,效率较低。 对于非线程安全的类和接口,在多线程中需要程序员自己处理线程安全问题。 Hashtable类的性能会低于HashMap类; |
|||||
●HashSet类是由哈希表支持。它不保证 set 的迭代顺序; 特别是它不保证该顺序恒久不变。此类允许使用 null 元素。 HashSet类为基本操作提供了稳定性能,这些基本操作包括 add、remove、contains 和 size,假定哈希函数将这些元素正确地分布在桶中。 Java的HashMap和Hashtable都实现了Map接口。它们及其子类都采用Hash算法决定Map中key的存储。 HashMap和Hashtable的主要区别有:线程安全性,同步(synchronization),以及速度。 |
|||||
●关于迭代器,其中hasNext()方法是判断是否有下一个元素,返回值为boolean, 而next()方法是获取下一个元素,一般这两个方法配合while循环一起使用! 遍历ArrayList时,可以通过Iterator迭代器,itor.hasNext()表示还有没有下一个集合元素,itor.next()取集合的下一个元素。 |
|||||
●Iterator接口描述的序列只能向后移动,这个从其提供的成员方法可以看出,next(),hasNext()。 其成员方法中,remove()是移出最后一个返回的序列成员。 next()是返回后一个序列成员(如果是第一次调用,则返回第一个成员), hasNext()表示是否还有序列成员。 |
|||||
●ListIterator接口的理解。Java中,除了具有Collection接口必备的iterator()方法外, List还提供listIterator()方法,返回一个 ListIterator接口。 作为ListIterator,ListIterator接口继承了Iterator接口,是List的专门迭代器。 和标准的Iterator接口相比,ListIterator增加了hasPrevious()、prevoius()、add()三个方法,可以向前或向后遍历数据,允许向List集合中添加数据。ListIterator接口的put()方法不能实现添加元素的功能个, |
|||||
LinkedList(): |
List<>: |
List(注释4会报错) |
TreeMap: |
||
Eg: |
foreach访问数组: |
||||
●泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。 这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。 在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患 泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。 如果一个类或接口上有一个或多个类型变量,那它就是泛型。类型变量由尖括号(“<>”)界定,放在类或接口名的后面。 |
|||||
●ava.util.Collections类包含很多有用的方法,可以使程序员的工作变得更加容易。 使用swap()方法可以在指定列表的指定位置处交换元素。 使用sort()方法可以根据元素的自然顺序 对指定列表按升序进行排序。 |
|||||
●泛型一样遵循多态,父引用指向子对象。 集合类都是泛型的,包括Iterator这个迭代器。 泛型是为了进行类型声明是不确定,编译时确定,从而简化程序的一种方式,所以会进行类型的检查。 泛型是能用尽可能使用-使程序更加健壮,避免运行时出现类型转换错误给用户带来麻烦。 |
|||||
Eg: |
分析: 本题考查泛型语句的语法。 Java的SortedSet是一个接口,其中的元素使用其自然顺序进行排序,或者根据通常在创建有序 set 时提供的 Comparator 进行排序。 该 set 的迭代器将按元素升序进行遍历。它提供了一些附加的操作来利用这种排序。 first()方法返回此 set 中当前第一个(最低)元素;tailSet()方法返回此 set 中大于等于指定的数值(方法的参数值)的所有元素。 对返回的set添加泛型时,应该在赋值运算符的左侧限定泛型类型。因此,本题应选择A。 |
||||
Eg: |
分析: 这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 如果一个类或接口上有一个或多个类型变量,那它就是泛型。 类型变量由尖括号<>界定,放在类或接口名的后面。 本题要求创建一个只能存放String的泛型ArrayList的语句, 选项A则是创建了一个存放int型数据的ArrayList对象; 选项C的赋值运算符左侧ArrayList类后面缺少<string>,存在语法错误; 选项D的赋值运算符左侧是ArrayList类,但其右侧是List接口,代码也有错误。本题应选择B。</string> |