java学习记录(12)——集合

来源:互联网 发布:php源码大全 编辑:程序博客网 时间:2024/05/23 09:54

Java集合框架的三个主要体系:Set、List、Map

Set代表无序、不可重复的集合;List代表有序、可重复的集合;Map代表具有映射关系的集合。

集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。所有集合类都位于java.util包下。

集合类只能保存对象,不能保存基本类型的值。

集合类主要有两个接口派生而出:Collection和Map。



Set集合类似一个罐子,把一个对象添加到Set集合时,Set集合无法记住添加这个元素的顺序,Set里的元素不能重复;List集合非常像一个数组,它可以记住每次添加元素的顺序,只是List的长度可变;Map集合也像一个罐子,只是它里面的每项数据都是由两个值key-value组成。

Iterator接口也是java集合框架的成员,主要用于遍历(迭代访问)Collection集合中的元素,Iterator对象也被称为迭代器。

Iterator接口隐藏了各种Collection实现类的底层细节,向应用程序提供了遍历Collection集合元素的统一编程接口,Iterator中定义了三种方法:

boolean hasNext():如果被迭代的集合元素还没有被遍历,则返回true

Object next():返回集合里下一个元素

void remove():删除集合里上一次next方法返回的元素

Iterator仅用于遍历集合,Iterator本身并不提供盛装对象的能力。如果创建Iterator对象,必须有一个被迭代的集合。

Collection books = new HashSet();

books.add("活着");

books.add("史记");

Iterator it = books.iterator();

while (it.hasNext()){

String book=(String)it.next();

System.out.println(book);}

foreach循环迭代访问集合元素更加便捷。

Collection books = new HashSet();

books.add("活着");

books.add("史记");

for(Object obj: books){

String book=(String)obj;

System.out.println(book);

}

foreach循环中的迭代变量也不是集合元素本身,系统只是依次把集合元素的值赋给迭代变量,修改迭代变量中的值没有任何实际意义。

Set接口

set集合不允许包含相同的元素,Set判断两个对象相同是根据equals方法,如果两个对象用equals方法返回true,Set就不会接受这两个对象。Set接口的三个实现类:HashSet、TreeSet、EnumSet

HashSet类

HashSet按照Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。

特点:

不能保证元素的排列顺序,顺序有可能发生变化;

HashSet不是同步的,如果多个线程同时访问一个Set集合,如果多个线程同时访问一个HashSet,如果2条或者2条以上线程同时修改HashSet集合时,必须通过代码来保证其同步;

集合元素值可以是null。

当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode()值,然后根据该hashCode值来决定该对象在HashSet中的存储位置。HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值也相等。

hashCode方法对于HashSet的作用是什么?

hash算法的功能:能保证通过一个对象快速查找到另一个对象。hash算法的价值在于速度,它可以保证查询得到快速执行。当需要查询集合中的某个元素时,hash算法可以直接根据该元素的值得到该元素保存在何处,从而可以让程序快速找到该元素。

HashSet集合里的元素都没有索引,实际上当程序向HashSet集合中添加元素时,HashSet会根据该元素的hashCode值来决定它的存储位置,每个元素的hashCode就是它的“索引”。HashSet采用每个元素的hashCode作为其索引,从而可以自由增加HashSet的长度,并可以根据hashCode值来访问元素。当从HashSet中访问元素时,HashSet先计算该元素的hashCode值,然后直接到该hashCode对应的位置去取出该元素,这就是HashSet速度很快的原因。

HashSet还有一个子类LinkedHashSet,LinkedHashSet集合也可以根据元素hashCode值来决定元素存储位置,但它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。

TreeSet类

TreeSet是SortedSet接口的唯一实现,TreeSet可以确保集合元素处于排序状态。因为TreeSet中的元素是有序的,所以增加了访问第一个、前一个、后一个、最后一个元素的方法。TreeSet采用红黑树的数据结构对元素进行排序,支持两种排序方式:自然排序和定制排序。

自然排序:TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间大小关系,然后将集合元素按升序排序。

定制排序:TreeSet可以实现定制排序,例如以降序排序,可以使用Comparator接口的帮助

EnumSet类

EnumSet类是一个专为枚举类设计的集合类,EnumSet中所有值都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式地指定。EnumSet的集合元素也是有序的,EnumSet以枚举类在Enum类内的定义顺序来决定集合元素的顺序。

HashSet和TreeSet是Set的两个典型实现,HashSet的性能总是比TreeSet好(特别是常用的添加、查询元素等操作),因为TreeSet需要额外的红黑树算法来维护集合元素的次序,只有当需要保持排序的Set时,才应该使用TreeSet,否则都应该使用HashSet。

List接口

List集合代表一个有序集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问指定位置的集合元素,List集合默认按元素的添加顺序设置元素的索引。

ListIterator接口继承了Iterator接口,提供了专门操作List的方法,ListIterator接口在Iterator接口基础上增加了如下方法:

boolean hasPrevious()::返回该迭代器关联的集合是否还有上一个元素。

Object previous():返回该迭代器的上一个元素。

void add():在指定位置插入一个元素。

ArrayList和Vector类都是基于数组实现的List类,都都封装了一个动态再分配的Object[]数组。每个ArrayList或Vector对象都有一个capacity属性,这个capacity表示它们封装的Object[]数组的长度,当向ArrayList或Vector中添加元素时,它们的capacity会自动增加。

固定长度的List:

Array.ArrayList是一个固定长度的List集合,程序只能遍历访问集合里的元素,不可添加、删除该集合里的元素。

Map接口

Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key,一组用于保存value,key和value都可以是任何引用类型的数据。key不允许重复。

把Map里所有key放在一起来看,它们就组成了一个Set集合(所有的key没有顺序,key与key之间不能重复)。

Map接口下有HashMap、LinkedHashMap、SortedMap(接口)、TreeSet、EnumSet等实现类和子接口。

HashSet和HashMap的性能选项:

对于HashSet及其子类而言,它们采用hash算法来决定集合中元素的存储位置,并通过hash算法来增加集合容积的大小;

对于HashMap及其子类而言,它们采用hash算法来决定Map中key的存储,并通过hash算法来增加key Set容积的大小。


0 0