顾名思义,容器就是用来盛放东西的。在生活中我们用杯子,木桶等等来盛放东西。而在程序中也有“容器”。他么用来盛放的是数据类型,这样一个个数据类型我们把他叫做元素。容器也被称为集合,在Java中,集合与容器是一个意思。
实际上,我们学过的数组就是容器的一种,他可以存放对象和基本数据类型。
数组的优势:是一种简单的线性序列,可以快速地访问数组元素,效率高。如果从效率和类型检查的角度讲,数组是最好的。
数组的劣势:不灵活。容量需要事先定义好,不能随着需求的变化而扩容。长度是固定的,当我们定义好它的长度时,就无法在原有的数组基础上进行改变。
基于我们学习过的数组,以及它并不能满足我们对“数据的存储和管理要求”,我们进一步来学习的容器,它是比数组更灵活,使用效率更高,可以随时扩容以满足我们使用要求的一种数据存储方式。以下是容器的类别图:
我们可以看到,容器的实质就是接口(intreface),一个是Collection接口,还有一个是Map接口。在Collection接口下有两个子接口,一个叫List,一个叫Set,因此这两个子接口继承了父类中所定义的一切方法,属性。接口必须要有实现类来实现它。因此:Set接口的实现类有HashSet,TreeSet。List接口的实现类有ArrayList,LinkedList,Vector。而Map接口的实现类有TreeMap,HashMap。
为了能够更好的学习容器,我们首先要先来学习一个概念:泛型。
泛型是JDK1.5以后增加的,它可以帮助我们建立类型安全的集合。在使用了泛型的集合中,遍历时不必进行强制类型转换。JDK提供了支持泛型的编译器,将运行时的类型检查提前到了编译时执行,提高了代码可读性和安全性。
泛型的本质就是“数据类型的参数化”。 我们可以把“泛型”理解为数据类型的一个占位符(形式参数),即告诉编译器,在调用泛型时必须传入实际类型。
下面我们来自定义泛型:
当我们没有定义泛型时,我们Object数组中的元素可以是任何类型
pubilc class TestGenerics{
pubic static void main(){
Collection tg = new Collection();
tg.setObject("孙悟空",2);
tg.getObejct(2);
tg.setObject(108000,3);
ta.getObject(3);
System.out.println(tg.getObject(3));
System,out.println(tg.getObject(2));
}
//定义一个数组
}
class Collection{
Object[] objs = new Object[5];
public void setObject(Object obj,int index){
objs[index] = obj;
}
public Object getObject(int index){
return objs[index];
}
}
现在我们定义泛型:泛型通常用字母T,E,V来表示,结构为
pubilc class TestGenerics{
pubic static void main(){
// 这里的”String”就是实际传入的数据类型;
Collection tg = new Collection<>();
tg.setObject("孙悟空",2);
tg.getObejct(2);
//tg.setObject(108000,3);
//ta.getObject(3);
//System.out.println(tg.getObject(3));
System.out.println(tg.getObject(2)); //原本是Object类型,加了泛型,直接返回String类型,不用强制转换;
}
//定义一个数组
}
class Collection{ // E:表示泛型
Object[] e = new Object[5];
public void setObject(E s,int index){ // E:表示泛型
e[index] = s;
}
public E getObject(int index){ // E:表示泛型
return (E)e[index]; // E:表示泛型。强制类型转换
}
}
泛型就相当于一个标签,当我们定义好泛型后,他就会将容器里面的元素作相应的规定,规定容器内元素的数据类型。这样就保证我们的容器内元素的一致性。我们在定义时(Collection
这样,代码中的不符合泛型“数据类型”的值就会报错。因此,泛型相当于给容器贴上标签,保证了容器的元素的一致性。
容器相关类都定义了泛型,我们在开发和工作中,在使用容器类时都要使用泛型。这样,在容器的存储数据、读取数据时都避免了大量的类型判断,非常便捷。
public class Test {
public static void main(String[] args) {
// 以下代码中List、Set、Map、Iterator都是与容器相关的接口;
List list = new ArrayList();
Set mans = new HashSet();
Map maps = new HashMap();
Iterator iterator = mans.iterator();
}
}
通过阅读源码,我们发现List、Collection、Set、Map、Set接口都定义了泛型,如下图所示:
因此,我们在使用这些接口及其实现类时,都要使用泛型。