容器与泛型

一.容器(collection)的定义

顾名思义,容器就是用来盛放东西的。在生活中我们用杯子,木桶等等来盛放东西。而在程序中也有“容器”。他么用来盛放的是数据类型,这样一个个数据类型我们把他叫做元素。容器也被称为集合,在Java中,集合与容器是一个意思。

实际上,我们学过的数组就是容器的一种,他可以存放对象和基本数据类型。

数组的优势:是一种简单的线性序列,可以快速地访问数组元素,效率高。如果从效率和类型检查的角度讲,数组是最好的。

数组的劣势:不灵活。容量需要事先定义好,不能随着需求的变化而扩容。长度是固定的,当我们定义好它的长度时,就无法在原有的数组基础上进行改变。

基于我们学习过的数组,以及它并不能满足我们对“数据的存储和管理要求”,我们进一步来学习的容器,它是比数组更灵活,使用效率更高,可以随时扩容以满足我们使用要求的一种数据存储方式。以下是容器的类别图:

 我们可以看到,容器的实质就是接口(intreface),一个是Collection接口,还有一个是Map接口。在Collection接口下有两个子接口,一个叫List,一个叫Set,因此这两个子接口继承了父类中所定义的一切方法,属性。接口必须要有实现类来实现它。因此:Set接口的实现类有HashSet,TreeSet。List接口的实现类有ArrayList,LinkedList,Vector。而Map接口的实现类有TreeMap,HashMap。



二.泛型(Generics)的定义以及定义一个泛型

           为了能够更好的学习容器,我们首先要先来学习一个概念:泛型。

           泛型是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来表示,结构为<T>或<T,E>。

pubilc class TestGenerics{
    pubic static void main(){
        // 这里的”String”就是实际传入的数据类型;
        Collection<String> 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>{      // 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<E>)的泛型就相当于一个形参,而我们在调用的时候就相当于给它定义成一个实参Collection<Sring>。泛型E像一个占位符一样表示“未知的某个数据类型”,我们在真正调用的时候传入这个“数据类型”。

这样,代码中的不符合泛型“数据类型”的值就会报错。因此,泛型相当于给容器贴上标签,保证了容器的元素的一致性。



 

三.容器中使用泛型

容器相关类都定义了泛型,我们在开发和工作中,在使用容器类时都要使用泛型。这样,在容器的存储数据、读取数据时都避免了大量的类型判断,非常便捷。

public class Test {
    public static void main(String[] args) {
        // 以下代码中List、Set、Map、Iterator都是与容器相关的接口;
        List<String> list = new ArrayList<String>();
        Set<Man> mans = new HashSet<Man>();
        Map<Integer, Man> maps = new HashMap<Integer, Man>();
        Iterator<Man> iterator = mans.iterator();
    }
}

通过阅读源码,我们发现List、Collection、Set、Map、Set接口都定义了泛型,如下图所示:

 

 因此,我们在使用这些接口及其实现类时,都要使用泛型。 

欢迎批评指正

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值