S2/JAVA/07-集合框架

集合位于java.util包中。

 

通常说的集合框架共有3大类接口:ListSetMap

他们的共同点:都是集合接口,都可以用来存储很多对象。

它们的区别如下:

Collection接口存储一组不唯一(允许重复)、无序的对象。

Set接口继承Collection接口,存储一组唯一(不允许重复)、无序的对象。

List接口继承Collection接口,存储一组不唯一(允许重复)、有序(以元素插入的次序来放置元素,不会重新排列)的对象。

Map接口存储一组成对的键-值对象,提供key(键)到value(值)的映射。Map中的key唯一,无序。Value同样不唯一,无序。

Iterator接口是负责定义访问和遍历元素的接口。

 

在集合框架中,List可以理解为数组,元素的内容可以重复并且有序。Set可以理解为数学中的集合,里面的数据不重复并且无序。Map可以理解为数学中的集合,只是每个元素都由keyvalue两个对象组成。

 

实现List接口的常用类有ArrayListLinkedList。他们都可以容纳所有类型的对象,包括null,允许重复,并且都保证元素的存储顺序。

ArrayList对数组进行了封装,实现了长度可变的数组。ArrayList存储数据的方式和数组相同,都是在内存中分配连续的空间。他的优点在于遍历元素和随机访问元素的效率比较高。

LinkedList采用链表存储方式,优点在于插入、删除元素时效率比较高。它提供了额外的addFirst()addLast()removeFirst()removeLast()等方法,可以在LinkedList的首部或尾部进行插入或删除操作。这些方法时的LinkedList可被用于堆栈(stack)或队列(quene)。

 

List接口的add(Object o)方法的参数类型是Object,即使在调用时实参是Dog类型,单系统认为里面只是Object,所以在通过get(int i)方法获取元素的时必须进行强制类型转换,如Dog dog=(Dog)dogs.get(i),否则会出现编译错误。

 

List接口中定义的各种常用方法

方法名称

说明

boolean add(Object o)

在列表的末尾顺序添加元素,起始索引位置从0开始

void add(int index,Object o)

在指定的索引位置添加元素,原索引位置及其后面的元素依次后移,注意:新添加元素的索引位置必须介于0和列表中元素个数之间,0可以元素个数不可以。

int size()

返回列表中的元素个数

Object get(int index)

返回指定订索引位置处的元素。注意:取出的元素是Object类型,使用前需要进行强制类型转换

boolean contains(Object o)

判断列表中是否存在指定元素

boolean remove(Object o)

从列表中删除元素

Object remove(int index)

从列表中删除指定位置元素,起始索引位置从0开始

 

VectorArray的异同。

ArrayList类出现之前,JDK中存在一个和他同样分配连续存储空间、实现了长度可变数组的集合类Vector。两者实现原理相同,功能相同,在很多情况下可以互用。Vector的用法可查询API文档。

 

VectorArrayList的主要区别如下。

Vetctor是线程安全的,ArrayList中速度、轻安全,是线程非安全的,所以当运行到多线程环境中时,需要程序员自己管理线程的同步问题。

当长度需要增长时,Vector默认增长为原来的一倍,而ArrayList只增长50%,有利于节约内存空间。

开发过程中,最好使用新版本的ArrayList

 

ArrayList采用了和数组相同的存储方式,在内存中分配连续的空间,在添加和删除非尾部元素时会导致后面所有元素的移动,性能低下。所以在插入、删除操作较频繁时,可以考虑使用LinkedList来提高效率。

 

LinkedList的一些特殊方法

方法名称

说明

void addFirst(Object o)

在列表的首部添加元素

void addList(Object o)

在列表的末尾添加元素

Object getFirst()

返回列表中的第一个元素

Object getLast()

返回列表中的最后一个元素

Object removeFirst()

删除并返回列表中的第一个元素

Object removeLast()

删除并返回列表中的最后一个元素

 

Map中的key不要求有序,不允许重复。Value同样不要求有序,但允许重复。最常用的Map实现类似HashMap,它的存储方式是哈希表。哈希表也称为散列表,是根据关键码值(key value)而直接进行访问的数据结构。也就是说你,他通过把关键码映射到表中一个位置来访问记录,以加快查找速度。存放记录的数组称为散列表。使用这种方式存储数据的优点是查询指定元素效率高。

 

Map的常用方法

方法名称

说明

Object put(Object key,Object value)

-值对的方式进行存储,注意:键必须是唯一的,值可以重复。如果试图添加重复的键,那么最后加入的-值对将替换掉原先的-值对

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()

从此映射中移除所有映射关系

 

 

HashtableHashMap的异同。

HashMap类出现之前,JDK中存在一个和他同样采用哈希表存储方式、同样实现键值映射的集合类Hashtable。两者实现原理相同,功能相同,很多情况向可以互用。

HashtableHashMap的主要区别如下。

Hashtable继承自Dictionary类,而HashMap实现了Map接口。

Hahstable是线程安全的,HashMap重速度、轻安全,是线程非安全的,所以当运行到多线程环境中时,需要程序员自己管理线程的同步问题。

Hashtable不允许null值(keyvalue都不允许),HashMap允许null值(keyvalue都允许)。

开发过程中最好使用新版本的HashMap

 

迭代器Iterator

Collection接口的Iterate()方法返回一个Iterator,然后通过Iterator接口的两个方法即可方便地实现遍历。

boolean hasNext():判断是否存在两一个可访问的元素。

Object next():返回要访问的下一个元素。

 

JDK1.5加入了增强型for循环,他是for语句的特殊简化版本,我们通常称之为foreach语句。Foreach语句格式:

for(元素类型元素不按量x:数组或集合对象){

引用了xjava语句

}

其中,t的类型必须属于数组或集合对象的元素类型。使用foreach语句遍历已经存储数据的Map对象,关键代码如下:

/*使用foreach语句输出集合中所有狗狗的信息*/

System.out.println("所有狗狗的昵称和品种分别是:");

Set keys=dogMap.keySet();                             //取出所有key集合

for(Object key:keys){

Dog dog=(Dog)dogMap.get(key);         //根据key取出对应的值

System.out.println(key+"\t"+dog.getStrain());

}

 

使用Iterator遍历List

//省略创建狗狗对象

/*创建ArrayList集合对象并把多个狗狗对象放入其中*/

List dogs=new ArrayList();

Dogs.add(ououDog);

Dogs.add(yayaDog);

Dogs.add(meimeiDog);

Dogs.add(2,feifeiDog);

/*通过迭代器依次输出集合中所有狗狗的信息*/

System.out.println("使用Iterator遍历,所有狗狗的昵称和品种分别是:")

Iterator its=dogs.iterator();

While(its.hasNext()){

Dog dog=(Dog)its.next();

System.out.println(dog.getName()+"\t"+dog.getStrain());

}

 

数组和集合的主要区别包括以下几个方面:

1、数组可以存储基本数据类型和对象,而集合中只能存储对象(可以以包装类形式存储基本数据类型)。

2、数组长度固定,集合长度可以动态改变。

3、定义数组时必须指定数组元素类型,集合默认其中所有元素都是Object

4、无法直接获取数组实际存储的元素个数,length用来获取数组的长度,但可以通过size()直接获取集合实际存储的元素个数。

5、集合有多种实现方式和不同的使用场合,而不像数组仅采用分配连续空间方式。

6、集合以接口和类的形式存在,具有封装、继承和多态等类的特性,通过简单的方法和属性调用即可实现复杂操作,大大提高了软件的开发效率。

7JDK中有一个Array类,专门用来操作数组,它提供一系列静态方法实现对数组搜索、排序、比较和填充等操作。JDK中有一个Collections类,专门用来操作集合,它提供一系列静态方法实现对各种集合的搜索、复制、排序和线程安全化等操作。

 

使用泛型集合在创建集合对象时指定集合中元素的类型,从集合中取出元素时无需进行类型强制转换,并且如果把非指定类型对象放入集合,会出现编译错误。

 

在以下定义的的ArrayList集合中,泛型为Object,向这个集合中存储的都是基本数据类型,但程序为什么不报错呢?

ArrayList<Object> list=new ArrayList<Object>();

list.add(12);

list.add(25.5);

list.add("");

list.add(true);

解答:代码中使用了包装类。包装类是指将基本类型封装到一个类中,也就是将基本类型包装成一个类类型。Java程序设计语言为每一种基本类型都提供了一个包装类。而这些包装类就在java.lang包当中,共有8个包装类,Object下有BooleanNumberCharacterNumber下又有ByteShortIntegerLongFloatDouble。所以共计有BooleanCharacterByteShortIntegerLongFloatDouble8个包装类。

Boolean类包装布尔类型,Character类包装的是字符,包装所有数字类型的类都继承自Number类,Number类是一个抽象类,包装了ByteShortIntegerLongFloatDouble等数字类型,并实现它所定义的方法,这些方法以不同数字格式返回对象的值。

1、包装类常用的构造方法

语法格式如:public Type(type value)

Type表示包装类,type代表基本类型。代码如下:

Integer intValue=new Integer(21);

Long longValue=new Long(21L);

Character charValue=new Character('x');

Boolean booleanValue=new Boolean(true);

Float floatValue=new Float(21F);

需要注意的是,一旦创建了某个包装类对象,该对象所代表的值就不能改变了。

2、常用的类型转换

1)包装类基本类型,语法格式如下。

public type typeValue()

示例代码如下。

Integer integerId=new Integer(25);

int intId=integerId.intValue();

 

Boolean bl=Boolean.valueOf(true);

boolean bool=bl.booleanValue();

2)字符串基本类型,语法格式如下。

public static type parseType(String type)

示例代码如下。

int num=Integer.parseType("36");

bool=Boolean.parseBoolean("false");

posted @ 2016-06-05 23:27  water5832  阅读(266)  评论(0编辑  收藏  举报