Java之集合框架和泛型

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 泛型的限定

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • 转载自:Java集合框架实例 1- 介绍 集合是程序和语言的基本思想。应用程序通常都会应用到集合,例如雇员的信息,...
    01_小小鱼_01阅读 379评论 0 1
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,497评论 18 399
  • 第十天 权限修饰符 public protected default private 同一类 true true ...
    炙冰阅读 514评论 0 1
  • 时光如梭。岁月在悄无声息中已度过了十九个年头。短暂而又漫长。童年的记忆稀稀疏疏的偶尔闪现着。如同隔了几个世纪。好多...
    霧原阅读 161评论 0 0
  • http://www.jianshu.com/p/5e98e10960d4?utm_campaign=haruki...
    宣峰阅读 103评论 0 0