Java-集合框架

序言

Java是一种面向对象语言,如果我们要针对多个对象进行操作,就必须对多个对象进行存储。而数组长度固定,不能满足变化的要求。所以,java提供了集合。
Java集合的特点:
1. 长度可以发生改变
2. 只能存储对象
3. 可以存储多种类型对象
Java集合与数组区别:
这里写图片描述


集合框架概述

Java平台提供了一个全新的集合框架。集合框架的核心接口为Collection、List(列表)、Set(集合)和Map(映射),如图所示:
集合框架
由于上面的框架图较为复杂,读者基本了解就可以,不需要全部记下来。将上面的关系图简化后,只需要读者记住的内容,如图所示:
Java集合简图
从图中可以看到,Collection是集合继承树中最顶层的接口,几乎所有的Java集合框架成员都继承实现了Collection接口,或者与其有密切关系。Collection提供了关于集合的通用操作。
Set接口和List接口都继承了Collection接口,而Map接口没有继承Collection接口。因此,Set对象和List对象都可以调用Collection接口的方法,而Map对象则不可以。

下面我们对这三种类型接口的结构加以说明:Set有点类似数学中集合的定义,是无序的、没有重复项目的集合。List是位置性集合,加进清单的元素可以加在清单中特定位置或加到末尾,可以保存重复的元素。Map用于关键字/数值对,其中关键字是数值的惟一标识(不可重复),用户可以按关键字存取数据,数据可重复。具体形式如图所示:
集合对比


1、Collection接口

Collection接口是集合框架最基础的接口,所以这个接口定义了整个集合框架都可以调用的方法,因此必须十分熟悉。Collection接口的定义方法如图所示。
Collection接口
而Collection接口常用方法如表所示。
这里写图片描述
知道了这些方法之后,我们就可以接着讨论实现他们的标准类了。标准的Collection实现类总结如表所示。
这里写图片描述


2、列表

List列表作为集合的一种,其主要特点在于其中的元素保持一定的顺序。本节将具体讲解List的两种实现类(ArrayList类和LinkedList类)的使用。

2.1、 ArrayList

ArrayList类是对AbstractList类的扩展。ArrayList支持可随需要而增长的动态数组。在Java中,标准数组是定长的。它们被创建之后,就不能被加长或缩短,也就意味着开发者必须先知道数组可以容纳多少元素。
一般情况下,只有在运行时才能知道需要多大的数组。为了解决这个问题,类集框架定义了ArrayList。ArrayList能够动态地增加或减小其大小。ArrayList有三种构造方法,如图所示。
这里写图片描述
ArrayList类的主要方法与功能描述如表所示。
这里写图片描述

2.2、LinkedList

LinkedList类是对AbstractSequentialList类的扩展。它提供了一个链接列表的数据结构。LinkedList类有两种构造方法,如图所示。
这里写图片描述
除了它继承的方法之外,LinkedList类本身还定义了一些有用的方法,这些方法主要用于操作和访问列表。它们具体的作用我们用图表示。
这里写图片描述


3、集合

Set集合是一种不包含重复元素的Collection,即Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。本节将介绍Set中的两个主要的类HashSet类和TreeSet类。

3.1、HashSet

HashSet类是对AbstractSet类的扩展。它创建了一个类集。该类集使用散列表进行存储,而散列表则通过使用称之为散列法的机制来存储信息。在散列中,一个关键字的信息内容被用来确定唯一的一个值,称为散列码。而散列码则被用来当作与关键字相连的数据的存储下标。HashSet类的构造方法如图所示。
这里写图片描述
图中所提到的填充比必须介于0.0与1.0之间。它决定在散列集合向上调整大小之前,有多少能被充满。具体地说,就是当元素的个数大于散列集合容量乘以它的填充比时,散列集合会被扩大。这里要注意的是,散列集合并不能确定其元素的排列顺序。如果需要排序存储,可以使用下面将会讲到的TreeSet类。HashSet类的主要方法及功能描述如表所示。
这里写图片描述
正如上面所说的一样,HashSet中的元素并没有按照顺序进行存储。

3.2、TreeSet

TreeSet为使用树来进行存储的Set接口提供了一个工具。对象按升序进行存储,这方便我们对其进行访问和检索。在存储了大量的需要进行快速检索的排序信息的情况下,TreeSet是一个很好的选择。TreeSet类的构造方法如图所示。
这里写图片描述
在TreeSet类中有几个特殊的方法及功能描述,如表所示。
这里写图片描述

3.3、通过迭代方法访问类集

通常我们会遇到要显示类集中每一个元素的情况,这时我们也许会想到用循环方法来完成。到目前为止,处理这个问题最简单的方法是使用iterator()。iterator()是一个或者实现Iterator,或者实现ListIterator接口的对象。Iterator可以完成通过循环输出类集内容,从而获得或删除元素。ListIterator是对Iterator的扩展,允许双向遍历列表,并且可以修改单元。
Iterator接口说明方法我们可以总结在表中。
这里写图片描述
现在我们来介绍使用迭代的方法。
在通过迭代方法访问类集之前,必须得到一个迭代方法。通常,使用迭代方法循环输出类集内容的操作步骤如图所示。
这里写图片描述
对于执行List的类集,也可以通过调用ListIterator来获得迭代方法。而且列表迭代方法提供了前向和后向访问类集的能力,并且可以修改元素。


4、映射

Java还在java.util中增加了映射。映射(map)是一个存储关键字和值的关联,或者说是“关键字/值”对的对象,即给定一个关键字,可以得到它的值。关键字和值都是对象,关键字必须是唯一的,但值是可以被复制的。

4.1、映射接口

映射接口定义了映射的特性和本质。支持映射的三大接口如图所示。
这里写图片描述
Map接口映射唯一关键字到值。关键字是以后用于检索值的对象。给定一个关键字和一个值,可以存储这个值到一个Map对象中。当这个值被存储以后,就可以使用它的关键字来检索它。Map.Entry接口使得可以操作映射的输入。而SortMap接口扩展了Map,它确保了各项关键字按升序排列。
Java提供了几个用来实现映射接口的类。可以被用作映射的类如表所示。
这里写图片描述

4.2、HashMap

HashMap类使用散列表实现Map接口。HashMap类的构造方法如图所示。
这里写图片描述
HashMap类的主要方法与功能描述如表所示。
这里写图片描述
HashMap实现Map并扩展AbstractMap。同HashSet一样,HashMap也不保证它的元素的顺序。
在向HashMap中添加元素时,不但要将元素添加,还要为每个元素设置一个Hash码。Hash码不只可以为数字,同样它也可以为字符串。

4.3、TreeMap

TreeMap类通过使用树实现Map接口。TreeMap提供了按排序顺序存储关键字/值对的有效手段,同时允许快速检索。不像散列映射,树映射保证它的元素按照关键字升序排序。TreeMap的构造方法如图所示。
这里写图片描述
TreeMap实现SortedMap并且扩展AbstractMap。本身并没有定义其他方法。
TreeMap的主要方法与功能我们可以用表表示。
这里写图片描述

4.4、map的遍历

第一种:KeySet()
将Map中所有的键存入到set集合中。因为set具备迭代器。所有可以迭代方式取出所有的键,再根据get方法。获取每一个键对应的值。 keySet():迭代后只能通过get()取key 。
取到的结果会乱序,是因为取得数据行主键的时候,使用了HashMap.keySet()方法,而这个方法返回的Set结果,里面的数据是乱序排放的。
典型用法如下:

Map map = new HashMap();
map.put("key1","lisi1");
map.put("key2","lisi2");
map.put("key3","lisi3");
map.put("key4","lisi4");  
//先获取map集合的所有键的set集合,keyset()
Iterator it = map.keySet().iterator();
 //获取迭代器
while(it.hasNext()){
Object key = it.next();
System.out.println(map.get(key));
}

第二种:entrySet()
返回此映射中包含的映射关系的 Set 视图。(一个关系就是一个键-值对),就是把(key-value)作为一个整体一对一对地存放到Set集合当中的。Map.Entry表示映射关系。entrySet():迭代后可以e.getKey(),e.getValue()两种方法来取key和value。返回的是Entry接口。
典型用法如下:

Map map = new HashMap();
map.put("key1","lisi1");
map.put("key2","lisi2");
map.put("key3","lisi3");
map.put("key4","lisi4");
//将map集合中的映射关系取出,存入到set集合
Iterator it = map.entrySet().iterator();
while(it.hasNext()){
Entry e =(Entry) it.next();
System.out.println("键"+e.getKey () + "的值为" + e.getValue());
}

推荐使用第二种方式,即entrySet()方法,效率较高。
对于keySet其实是遍历了2次,一次是转为iterator,一次就是从HashMap中取出key所对于的value。而entryset只是遍历了第一次,它把key和value都放到了entry中,所以快了。两种遍历的遍历时间相差还是很明显的。


5、集合比较

TreeSet和TreeMap都按排序顺序存储元素。然而,精确定义到底采用哪种“排序顺序”则是比较方法。在默认情况下,Java采用的是“自然排序”的顺序存储它们的元素,例如A在B的前面,2在3的前面,等等。如果需要用到其他的方法对元素进行排序,可以在构造集合或者映射时,指定一个Comparator对象。
Comparator接口定义了两种方法:compare()和equals()。compare()方法的用法如图所示。
这里写图片描述
而equals()方法的用法如图所示。
这里写图片描述
但是在实际应用中是没有必要去重载equals()方法的。所以在这里我就不再为大家举例了。


6、从前版本的类和接口

java.util的最初版本中不包括类集框架。它定义了几个类和接口提供专门的方法用于存储对象。随着Java引入类集,有几种最初的类被重新设计成支持类集接口,因此它们与框架完全兼容。由Java定义的以前版本的类大致有:Vector、Stack、Dictionary、Hashtable和Properties。下面我们一一对其进行简要介绍。

6.1、Vector类

Vector类实现动态数组,这与ArrayList相似,但两者不同的是:Vector类是同步的,并且它包含了一些不属于类集框架的方法。但被重新定义后,Vector类已经完全兼容于类集框架了。Vector类的构造方法如图所示。
这里写图片描述
所有的矢量开始都有一个原始的容量。在这个原始容量达到之后,下次再存储时,矢量会自动为那个对象分配空间。通过分配超过需要的内存,矢量减小了可能产生的分配的次数,节约了时间。
Vetor提供了用于增加元素的方法,我们总结在表中。
这里写图片描述

6.2、Stack类

在栈的操作中,先压入栈的元素在栈的最底部,删除元素是从栈顶开始的。也就是最后压入栈的元素将会被先删除掉。

6.3、Dictionary类

字典(Dictionary)是一个表示关键字/值存储库的抽象类,同时它的操作和映射(Map)很类似。给定一个关键字和值,可以讲值存储到字典对象中。一旦这个值被存储了,就能够用关键字来检索它。因此与映射一样,字典可以被当做关键字/值对列表来考虑。但在当前版本的Java中,Dictionary类已经被Map类所取代,所以被认为已是过时的。所以我们也不再作详细的讨论,只要清楚其和映射的作用相同就可以了。

6.4 Hashtable类

散列表(Hashtable)是java.util的一部分,同时也是Dictionary的具体实现。现在的Hashtable已经被集成到类集框架中。它与HashMap相似,但Hashtable是同步的。使用Hashtable时,指定一个对象作为关键字,同时指定与该关键字相关联的值。接着该关键字被散列,把得到的散列值作为存储在表中的值的下标。Hashtable的构造方法如图所示。
这里写图片描述
第三种形式中,填充比必须介于0.0和1.0之间,它决定了在散列表向上调整大小之前的充满度。即当元素的个数大于散列表的容量乘以它的填充比时,散列表被扩展。如果没有指定填充比。则默认使用0.75。

6.5 Properties类

属性(Properties)是Hashtable类的一个子类。它用来保持值的列表,其中关键字和值都是字符串。Properties类被许多其他的Java类所使用。例如,当获得系统环境值时,System.get Properties()返回对象的类型。Properties类定义的构造方法如图所示。
这里写图片描述


总结

在这一章中我给大家介绍了Java集合框架,主要包括集合框架的概念、集合框架接口,以及列表、集合、映射三种结构还有迭代方法、比较方法和较早以前版本的类和接口等内容。

猜你喜欢

转载自blog.csdn.net/weixin_39190897/article/details/81774724