内容导航
Java语言中的集合就像一个容器,用来存放Java类的对象,并且可以实现常用的数据结构。本章将详细
介绍java中的集合,主要内容包括集合相关概念,List接口,Set接口和Map接口,以及ArrayList类,LinkedList类,HashSet类和HashMap类等,除此之外,还会介绍集合送代器Iterator。
Java集合概述
为什么用集合,应为数组有不足点,数组的短处:
数组长度固定不变
不便存储具有映射关系的数据
数据变更效率低下
集合框架
java集合框架提供了一套性能优良,使用方便的接口和类,它门都位于Java。util包中,集合中的元素全部是对象,即Object类的实例,不同的集合类有不同的功能和特点,适合不同的场合。
从图中可以看出,Java的集合类主要由两个接口派生而成;Collection接口和Map接口。Collection接口和Map接口是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。其中,Collection接口常用的子接口包含List接口和Set接口;另外一个重要接口是Map接口,它是独立一支,以上三者都是集合接口,其实实现类为Java中经常使用的集合类型。Java集合框架常用接口说明如表所示。此外,Java集合框架还包括相关的工具类(Iterator送代器接口,Arrays类和Collections类)。
名称 |
描述 |
Collection
扫描二维码关注公众号,回复:
14678258 查看本文章
|
|
Set |
继承Collection接口,存储一组不可重复的无序对象 |
List |
|
Map |
|
Iterator |
集合送代器,能够遍历集合元素的接口 |
Collections |
|
Collection接口
Collection接口是List接口,Set接口的父接口,该接口中定义的方法既可以操作Set集合,也可以用与操作List集合。Collection接口常用的方法如表所示。
方法 |
描述 |
boolean add(Object o) |
用于向集合中添加一个元素,如果集合不允许重复且已包含了指定元素,则返回false |
boolean addAll(Collection c) |
将集合c里的所有元素添加到指定集合里,添加成功返回true |
void clear() |
清除集合中所有元素,将集合长度变为0 |
boolean contains(Object o) |
判断集合中是否包含指定元素 |
boolean containsAll(Collection c) |
判断集合中是否包含集合c里的所有元素 |
boolean remove(Object o) |
删除集合中的指定元素o,当集合中包含了一个或多个元素o时,这些元素将被删除,删除成功返回true |
int size() |
返回集合里元素的个数 |
boolean retainAll(Collection c) |
从集合中删除集合c里不包含的元素(相当于把调用该方法的集合变成该集合和集合c的交集),如果该方法改变了调用该方法的集合,则该方法返回true |
boolean removeAll(Collection c) |
从集合中删除集合c中包含的元素(相当于用调用该方法的集合减集合c),如果删除了一个或一个以上的元素,则该方法返回true |
boolean isEmpty() |
如果集合中不包含任何元素,则该方法返回true |
Object[] toArray() |
把集合转换成一个数组,所有的集合元素变成对应的数组元素 |
提示:
Java集合中的元素全部是对象,是引用类型,不能存储基本数据类型元素。如果强制添加,则其会自动封装成对象。
使用System。out.println()方法输出集合数据时,需要调用集合类型本身的toString()方法,该方法会进一步调用集合元素的toString()方法。
集合中存储的元素为Object类的对象,属于引用数据类型,默认调用Object的toString()方法进行输出,输出格式为:getClass().getName()+"@"+Integer.toHexString(hashcode()) 即“该对象所属类全称的字符串@该对象哈希码的无符号的十六进制表示”
集合的遍历
当使用System.out.println()方法输出集合对象时,其将以【ele1,ele2……】的形式输出,这是因为所有的Collection实现类都重写了toString()方法,该方法可以一次性地输出集合中的所有元素。但是,如果想依次访问集合里的每一个元素,并实现对该元素的操作,则需要使用某种方式遍历集合元素。下面介绍遍历集合的两种方法。
使用Iterator接口遍历集合元素,Iterator接口定义的方法
方法 |
描述 |
boolean hasNext() |
判断是否存在下一个遍历元素,存在则返回true |
Object next() |
返回遍历的下一个元素 |
void remove() |
删除集合里上一次next()方法返回的元素 |
使用for循环遍历集合元素,语法:
for(数据类型type 送代变量名value:送代对象 object){
//引用送代变量value的语句
}
List
List集合是一类存储元素有序,可重复的集合,集合中每个元素都有对应的索引。List集合允许使用重复元素,可以通过索引访问指定位置的集合元素。List集合默认按元素的添加顺序设置元素的索引,如果引为0,1,2,3……。
List概述
List接口作为Collection接口的子接口,可以使用Collection接口定义的全部方法。由于List集合是有序集合,所以List接口在Collection接口方法基础上,另外扩展了一些根据索引操作集合元素的方法。
List接口扩展的方法
方法 |
描述 |
void add(int index,Object element) |
将元素(element)插入List集合的指定位置(index) |
boolean addAll(int index,Collection c) |
将集合c所包含的所有元素都插入List集合的指定位置(index) |
Object get(int index) |
返回集合index索引处的元素 |
int indexOf(Object o) |
返回对象o在List集合中第一次出现的位置索引 |
int lastIndexOf(Object o) |
返回对象o在List集合中最后一次出现的位置索引 |
Object remove(int index) |
从集合中删除指定位置的元素 |
boolean remove(Object o) |
从集合中删除指定对象 |
Object set(int index,Object element) |
将index索引处的元素替换成Element对象,返回新元素 |
List subList(int fromIndex,int toIndex) |
返回从索引包含(fromlndex)到索引不包括(toIndex)处所有集合元素组成的子集合 |
List集合比Collection接口扩充了更多的方法,而且这些方法操作起来很方便,需要通过List接口的子类实例化对象调用。常用的子类有ArrayList类和LinkedList类,它们的集合对象都可以容纳所有类型的元素对象,包括null,允许重复,并且保证元素按顺序存储。
ArrayList集合类
ArrayList类对数组进行了封装,实现了长度可变的数组。ArrayList集合存储数据的方式和数组相同,都是在内存中分配连续的空间。
LinkedList集合类
由于ArrayList集合采用了和数组相同的存储方式,在内存中分配连续的空间,当添加和删除非尾部元素时会导致后面所有元素的移动,性能低下,所以在插入,删除操作较频繁时,可以考虑使用LinkedList集合提高效率。
LinkedList集合存储数据的方式为双向链表存储方式,它的每个节点都有两个指针,分别指向直接后续和直接前驱。它提供了额外的addFirst(),addLast(),removeFirst()和removeLast()等方法,可以在链表的首部或尾部进行插入或删除操作。
LinkedList集合实现链表操作的常用方法
方法 |
描述 |
void addFirst(Object o) |
在链表的首部添加元素 |
void addLast(Object 0) |
在链表的未尾添加元素 |
Object getFirst() |
返回链表中第一个元素 |
Object getLast() |
返回链表中最后一个元素 |
Object removeFirst() |
删除并返回链表中的第一个元素 |
Object removeLast() |
删除并返回链表中的最后一个元素 |
小结:
ArrayList集合和LinkedList集合对比如下。
ArrayList集合的底层是数组。
优点:基于数组实现,读取操作效率高。
缺点:不适合频繁进行插入和删除操作,因为每次执行该类操作都需要频繁移动其中的元素。
LinkedLIst集合由双向链表实现,从任意一个节点开始,都可以很方便地访问它的前驱节点和后续节点。
优点:增加,删除操作只需要修改链表节点指针,无需进行频繁的移动。
缺点:遍历效率较低。
Set
Set接口和List接口一样,都是Collection的子接口,它类似于一个罐子,丢进Set集合里的多个对象没有明显的顺序。Set集合于Collection集合基本上一样,没有提供额外的方法,只是行为上略有不同,Set集合不允许包含重复元素。
HashSet集合
HashSet类是Set接口的典型实现,使用HashSet集合可以实现对无序不重复数据的存储,具有很好的存取和查找性能。它具有以下特征。
不允许存储重复的元素。
没有索引,没有包含索引的方法,不能使用索引遍历。
是无序集合,存储元素和取出元素的顺序可能不一致。
Map
List集合和Set集合都可以存储一组数据元素,每个元素是一个对象,并且可以实现对这组数组元素的操作。当是,有时候需要存储具有映射关系的数据元素,如字典数据,可以通过中文找到对应的英文单词,每个元素由具有一对一关系的一组中英文数据组成,也就是一组成对的键-值对象,而不是单值数据,这样通过List集合和Set集合无法实现,需要使用到Map集合。
Map概述
Map集合可以存储若干个成对的键-值对象,提供键(Key)到值(value)的映射。其中key为Set集合类型,不要求有序,不允许重复;value同样不要求有序,但允许重复。因为Map接口与Collection接口不存在继承关系,所以Map集合对象不能使用Collection接口中定义的方法,而使用持有能够操作“键-值对”的方法。
Map接口的常用方法
Object put(Object key,Object value) |
以“键-值对”的方式存储。 注意:键必须是唯一的,值可以重复。如果试图添加重复的键,那么最后加入的“键-值对”将替换掉原先的“键-值对” |
Object get(Object key) |
返回指定的键所对应的值;如果此Map集合中不包含指定的键,则返回null |
int size() |
返回元素个数 |
boolean remove(Object key) |
删除指定的键映射的“键-值对” |
Set keyset() |
返回键的集合 |
Collection values() |
返回值的集合 |
boolean containsKey(Object key) |
若存在指定的键映射的“键-值对”,则返回true |
Set entrySet() |
返回“键-值对”集合 |
boolean isEmpty() |
若不存在“键-值对”元素,则返回true |
void clear() |
删除该Map对象中所有“键-值对” |
HashMap集合类
Map集合可以存储成对出现的“键-值对”元素,它的存储方式是哈希表。哈希表为散列表,是根据关键码值直接访问的数据结构。也就是说,它通过把关键码来映射到表中的一个位置来访问记录,以加快查找速度。存放记录的数组被称为散列表。使用这种方式存储数据的优点是查询指定元素效率高。
对比:
在Map接口的实现类中,除HashMap外,Hashtable对象也可以存储“键-值对”对象,Hashtable类与HashMap类具有相似的特征,Hashtable类是一个古老的Map接口实现类,Hashtable类和HashMap类之间存在着以下典型区别。
Hashtable类是线程安全的Map实现,但HashMap类是线程不安全的,HashMap性能更高,但如果多个线程访问一个Map集合对象,则应选择Hashtable类
Hashtable类不允许使用null作为key和value,HashMap类可以使用null作为key或value.
因为HashMap类里的key不能重复,所以在HashMap类里最多只有一个“键-值对”元素的key为null,但可以有多个“键-值对”元素的value为null。
HashMap集合的遍历
对于Map接口来说,其本身是不能直接使用送代(如Iterator,foreach)进行输出的。由于Map中的每个位置存入的是“键-值对”,而Iterator送代器每次只能找到一个值,可以先获取所有键的集合,通过遍历键的集合,找到每个键对应的值,
扩展资料:
在Map中定义了一个接口Map.Entry,用户保存形式如“key-value”的元素,即“键-值对”元素。
Map.Entry接口的常用方法
方法 |
描述 |
Object getKey() |
取得此“键-值对”对应的key值 |
Object getValue() |
取得此“键-值对”相对应的value值 |
int hashCode() |
返回该“键-值对”的哈希码值 |
Object setValue(Object value) |
用指定的值替换该“键-值对”的value值 |
泛型集合
泛型可以约束录入集合的元素类型,大大提高了数据安全性,从集合中取出数据无需进行类型,从而让代码更简洁,查询更加健壮。如果要锁定基本数据类型,那么要写该类型的包装类。
数据类型 |
包装类 |
|
整形 |
byte |
Byte |
short |
Short |
|
int |
Integer |
|
long |
Long |
|
浮点型 |
float |
Float |
double |
Double |
|
字符型 |
char |
Character |
应用泛型
泛型集合可以约束集合中元素的类型,它可以把类型当作参数一样传递。泛型集合的形式为List<E>,Map<K,V>等,其中<E>,<K,V>是集合类型形式的参数,可以在创建集合时,指定这些类型参数,即元素的数据类型,添加的元素必须为指定类型对象,保证数据的安全性。
public class Teacher {
private int age;//年龄
private String name;//年龄
public Teacher() {
}
public Teacher(int age, String name) {
this.age = age;
this.name = name;
}
public class Student {
private String name;
private String id;
public Student() {
}
public Student(String name, String id) {
this.name = name;
this.id = id;
}
public class Test {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
list1.add(new Teacher(12,"小帅"));
ArrayList<Teacher> j= list1;
ArrayList<Teacher> a= arr();
for (Teacher th:a){
//打印到第二条的时候,必然报错,不用想的
System.out.println(th.toString());
}
//可以先在数据类型定义泛型,后面就不需要了。
ArrayList<Teacher> list = new ArrayList<>();
//如果添加了其他类,那么就会报错
//list.add(new Student("小破","12"));
list.add(new Teacher(12,"zhu"));
}
public static ArrayList arr(){
ArrayList list = new ArrayList();
list.add(new Teacher(12,"qw"));
list.add(new Student("12","19"));
return list;
}
}
本章总结
集合弥补了数组的缺陷,它比数组更灵活更实用,可大大提高软件的开发效率,而且不同的集合可用于不同场合。
Java 的集合类主要由两个接口派生而出: Collection 接口和Map 接口及相关的工具类,这两个接口又包括了一些子接口或实现类。其中,Collection 接口又包含子两个子接口--List 接口和Set 接口,另外一个重要接口是Map 接口。
Collection 接口存储一组不唯一、无序的对象。
Set 接口继承 Collection 接口,存储一组唯一、无序的对象。
List 接口继承 Collection 接口,存储一组不唯一、有序的对象。
Map 接口存储一组成对的键-值对象,提供从 key到 value 的映射。key不要求有序,不允许重复;value 同样不要求有序,但允许重复。
Iterator 为集合而生,专门实现集合的遍历。它隐藏了各种集合实现类的内部细节,提供了遍历集合的统一编程接口。
ArrayList 类和数组采用相同的存储方式,它的优点在于遍历元素和随机访问元素的效率比较高。
LinkedList 类采用链表存储方式,优点在于插入,删除元素时效率比较高。
HashMap 类是最常见的 Map 实现类,它的存储方式是哈希表,优点是查询指定元素效率高。使用泛型集合在创建集合对象时指定集合中元素的类型,在从集合中取出元素时无需进行强制类型转换,避免了 ClassCastException 异常。
一份信心,一份努力,一份成功;十分信心,十分努力,十分成功