美文网首页
Java之集合框架和泛型

Java之集合框架和泛型

作者: 如果仲有听日 | 来源:发表于2018-08-06 15:31 被阅读0次

1. 集合介绍

集合是java中提供的一种容器,可以用来存储多个数据。由java基础语法中得知,如果数据多了,可以使用数组或者ArrayList集合来存放。

数组和集合的区别:

    数组的长度是固定的,集合的长度是可变的

    集合中存储的元素必须是引用类型

集合学习的目标:

    集合本身是一个存储的容器:

        必须能用集合存储对象

        能够增加元素、遍历集合

        能够掌握不同集合的特性

2. 回顾ArrayList集合

ArrayList比数组的好处是,存储的元素长度可变。

ArrayList原则上不存储基本类型,如果是基本类型,是自动装箱存储。

2.1 对基本类型的操作

public static void addShowArrList() {

    ArrayListarr = new ArrayList();

    arr.add(11); arr.add(22);

    arr.add(33); arr.add(44);

    arr.add(55); arr.add(66);

    for(int i = 0; i < arr.size(); i++) {

        System.out.println(arr.get(i));

    }

    arr.remove(2);

    for(int i = 0; i < arr.size(); i++) {

        System.out.println(arr.get(i));

    }

}

2.2 对引用类型的操作

定义一个Persion类:

public class Person {

    private String name;

    private int age;


    public Person() {

    }


    public Person(String name, int age) {

        Super();

        this.name = name;

        this.age = age;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

    public String toString() {

        return "Person [name=" + name + ", age=" + age + "]";

    }

}

测试代码:

public static void addShowArrList2() {

    ArrayListarrPerson = new ArrayList();

    arrPerson.add(new Person("aaa", 20));

    arrPerson.add(new Person("bbb", 25));

    arrPerson.add(new Person("ccc", 30));

    for (int i = 0; i < arrPerson.size(); i++) {

        System.out.println(arrPerson.get(i)); //这里因为Person中重写了toString方法,所以不是打印对象地址

    }

}

3. 集合的继承关系

查阅API手册,发现ArrayList类它继承了抽象类AbstractList,同时实现接口List,而List接口又继承了Collection接口。所以Collection接口为最顶层的集合接口了

interface List extends Collection{

}

public class ArrayList extends AbstractList implements List{

}

根据源码片段,说明使用ArrayList类时,该类已经把所有抽象方法进行了重写。那么,实现Collection接口的所有子类都会进行方法重写。

    Collection接口常用的子接口有:List接口、Set接口

    List接口常用的子类有:ArrayList类、LinkedList类

    Set接口常用的子类有:HashSet类、LinkedHashSet类

Collection接口是集合中的顶层接口,它中定义的所有功能子类都可以使用。

Collection表示一组对象,这些对象也称为Collection的元素。

    List派系的Collection允许有重复的元素,而Set派系的则不允许有重复元素。

    List派系的Collection是有序的,而Set派系的则是无序的集合


4. 集合Collection

4.1 Collection的add, clear方法

add, clear是Collection类的抽象方法,ArrayList最终将他们实现了,用ArrayList举例

Collection接口中的方法是集合中所有实现类必须拥有的方法

    List extends Collection

    ArrayList implements List

add方法向集合添加元素;clear方法清空集合,但是不会删掉集合

4.2 contains、size方法

private static void testFunc2() {

    Collectioncoll = new ArrayList();

    coll.add("abc");

    coll.add("def");

    coll.add("ghi");

    System.out.println(coll);

    System.out.println(coll.contains("def"));

    System.out.println(coll.contains("acb"));

    System.out.println(coll.size());

}

4.3 引申获取长度的方式

    Java中获取长度的三种方式,都返回int型:

        数组.length

        字符串.length()

        集合.size()

private static void testFunc3() {

    int[] arr = new int[3];

    System.out.println(arr.length);

    String str = "kasdlfjklsdfj";

    System.out.println(str.length());

    Collectioncoll = new ArrayList();

    coll.add("abc");

    coll.add("def");

    coll.add("ghi");

    System.out.println(coll);

    System.out.println(coll.size());

}

4.3 toArray方法

把集合转成数组, 返回是一个存储对象的数组

private static void testFunc3() {

    Collectioncoll = new ArrayList();

    coll.add("abc");

    coll.add("def");

    coll.add("ghi");

    System.out.println(coll);

    Object[] obj = coll.toArray();

    for(int i = 0; i < obj.length; i++) {

    System.out.println(obj[i]);

    }

}

将集合转为数组,这样数组中的集合信息就不能被修改

4.4 remove方法

删除集合中的指定参数

private static void testFunc4() {

    Collectioncoll = new ArrayList();

    coll.add("abc");

    coll.add("def");

    coll.add("ghi");

    System.out.println(coll);

    

    System.out.println(coll.remove("def"));

    System.out.println(coll);

}

特别注意:因为ArrayList类是List派系的,是允许有重复元素的,在remove的时候实际上会删除第一个集合中的元素

5. Iterator接口:迭代器,获取集合元素

由于Java中有多种集合,它们在存储元素时,采用的存储方式不同,我们要取出这些集合中的元素,可通过一种通用的获取方式来完成。

屏蔽了不同集合获取元素的不同

5.1 Iterator实现原理

迭代器的运用,使用了面向接口的编程思想:

Iterator是一个接口,使用它必须找到实现类

在Collection接口中有一个iterator方法, 返回Iterator:Iterator<E>iterator()

子类ArrayList实现了iterator方法

ArrayList的iterator()方法,返回的是是Iterator接口的实现类的对象

Iterator it = array.iterator(), it就是Iterator接口的实现类,是由ArrayList对象array的iterator方法返回的

5.2 Iterator代码实现

引申1:如果将ArrayList改为HashSet,意思为使用HashSet集合来添加元素,使用Iterator取出HashSet中的元素。取出时,由于HashSet是Set派系的,Set派系是无须集合,所以Iterator取出时是无序的,且在添加元素时是不能重复的:

引申2:使用for循环也能使用迭代器

    使用for的唯一好处是由于it是在for中定义的,因此退出for之后,it的存储空间立即被释放,比while节约空间

for(Iterator it = coll.iterator(); it.hasNext(); ) {

    System.out.println(it.next());

}

5.3 Iterator执行过程

5.4 集合迭代中的转型(不建议这样使用,尽量使用泛型)

集合可以存任意类型的对象

集合中,不指定存储的数据类型,因此它什么都可以存

特别注意:如果要使用默认类型的特有方法,必须进行向下转型

6. 增强型for循环

参考:https://www.jianshu.com/p/856ec374ff4e

也是三种遍历数组的方式之一

从JDK1.5开始Collection强行继承了Iterable接口,只有一个目的,就是要让集合使用foreach方法

6.1 foreach遍历数组

优势:简化代码,方便遍历容器

劣势:int a只是一个变量,arr中的元素赋值给a,arr内存中的数据无法被改变

6.2 foreach遍历集合

Person类:

需要导包:导包外的包中的Person类

7. 泛型

7.1 泛型概述

在5.4中,由于定义集合Collection时没有声明元素类型,因此同一个集合中可以add任何类型的数据,虽然遍历时打印元素不会出现问题,但要使用到强转类型时就会报错:Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

在JDK1.5开始就引入了泛型这种安全机制,保证程序的安全性

泛型:指明了集合中存储的数据类型,用一对<>表明:<数据类型>

这样,如果添加了非泛型的数据类型,编译器是会报错的

有了泛型,再使用泛型数据类型的特有方法时,也不需要进行类型强转了

引申:

JAVA的泛型是伪泛型,使用了泛型<数据类型>只是针对编译器生效。在编译生成的class文件中,其实是没有泛型的表现的(可以通过java反编译成源码查看,反编译出来的代码没有泛型),但这样也足够安全了。

据说C++的泛型是真泛型

7.2 带有泛型的类

使用过的ArrayList是我们最熟悉的带有泛型的类

    public class ArrayList<E>

其中E是Element的简写,理解为一个变量类型,E是什么类型,ArrayList集合中就存什么类型,而且其成员方法都带有<E>

    public boolean add(E e)

    Iterator<E> it = arr.iterator();

例子见Iterator

7.3 带泛型的方法

看一段ArrayList类的add方法:

定义ArrayList方法使用的泛型类型是什么, 泛型方法的E就是什么类型

7.4 带泛型的接口

List接口就是一个带泛型的接口

api手册中倒找List接口

可见,我们在项目中定义类的时候,可以先实现接口,不理会泛型,这样,调用者在new对象的时候再来指定类型

7.5 使用泛型的好处总结

    解决了强转时的安全问题

    将错误从运行时提前到了编译时

    增加了开发和调用者的灵活性

    泛型的出现,带来了增强型for循环foreach的出现

7.6 泛型通配符 ?

例:定义一个函数,可以同时迭代不同泛型类型的集合

可见,由于ArrayList是List派系的,HashSet是Set派系的,因此参数必须使用List和Set派系的父类接口Collection。总之需要向上找相同的父类。

由于?通配符不知道什么类型,因此不能做强转

7.7 泛型的限定

相关文章

  • 《Kotlin入门实战》CH8 | 泛型

    泛型 泛型是在Java5中引入的,泛型让集合框架可以重用代码,在没有泛型时候,集合框架中存储数据的类型都是Obje...

  • 集合

    集合 Java集合框架 将集合的接口和实现分离 Collection接口 迭代器 泛型使用方法 集合框架中的接口 ...

  • 深入学习java系列之集合框架

    集合概述 java 集合部分主要有 java 集合框架相关的内容和 java 泛型相关的内容。 集合是用来做什么的...

  • Java之集合框架和泛型

    1. 集合介绍 集合是java中提供的一种容器,可以用来存储多个数据。由java基础语法中得知,如果数据多了,可以...

  • Java高级技术小结(week13)

    集合框架和泛型 实用类(包装类, Math, String大类, java.util<日期时间, Random>)...

  • 四、Java高级--1、泛型

    泛型定义:数据类型参数化,提前定义好集合中放入什么类型集合框架中没使用泛型和使用泛型的比较 泛型规则和限制1、泛型...

  • java泛型详解

    泛型是Java中一个非常重要的知识点,在Java集合类框架中泛型被广泛应用。本文我们将从零开始来看一下Java泛型...

  • 05-Java基础-集合框架& List & Map

    集合框架、generic泛型、List、Set、Map、Collections类 集合框架 数组和集合的区别:1....

  • 2018-07-16

    Java 阅读 大白话说Java泛型 深入理解Java集合框架 java构造代码块详解 Java中Overload...

  • java中泛型的正确使用姿势

    泛型是Java中一个非常重要的知识点,在Java集合类框架中泛型被广泛应用。利用好泛型,在系统架构中是一把利器。 ...

网友评论

      本文标题:Java之集合框架和泛型

      本文链接:https://www.haomeiwen.com/subject/fxzyvftx.html