Java进阶学习第十五节——集合框架

1.课程介绍

  1. java集合框架学习 HashSet
  2. Java集合框架学习 Map
  3. Generic <泛型>

在这里插入图片描述

针对数组提供了length属性来获取数组的长度
针对字符串提供了length()方法来获取字符串的长度
针对泛型集合类提供了size()方法来获取元素的个数

2. HashSet

2.1 语法特点:不重复,无序(不保证和添加顺序一致)
1、不能够添加重复元素
2、初体验
在这里插入图片描述

通过一步步测试发现:我们不同HashSet内部到底是如何判断重复的?

3、判断重复的方式:
① 通过添加进去的元素的hashCode+eqauls 两者进行比较
② 如果两个对象的hashCode相等 并且 两个对象调用equals结果是true 才认为两个元素重复
③ 示意图
在这里插入图片描述

④ 验证上面的规则
1 打印上面示例中的元素的hashCode和equals的结果
2 尝试自定义类,覆写hashCode 和 equals 这两个方法中的代码随便写
在这里插入图片描述

⑤ 实际开发情况分析(重点)

1、从上面的示例来看,结果两个都添加进去了,原因:hashCode不等,equals为false
2、从业务上来看(需要向源码时代学生管理系统中添加两个学生信息),觉得这两天数据是同一个人
3、应该怎么做: 在Student中覆写hashCode 和equals方法
4、怎么覆写?
覆写的时候应该参考实际业务中的比较规则,例如姓名,年龄等(还得看Student类中有哪些字段,并且这些字段是业务人员判断的标准)

3. 自然排序与定制排序(比较器)

Comparator接口:
强行对某个对象进行整体排序的比较函数
可以将Comparator传递给sort方法

第一步:建立一个比较器类实现Comparator接口
第二步:实现comparTo方法,重写
第三步:测试 Collections.sort(集合,比较器)

在这里插入图片描述

字符串.compareTo(字符串) 返回一个int类型,返回的值与上图相同

Comparable接口:

(比较方法也是comparTo比较,返回类型是int,返回值与上图相同)
此接口强行对实现它的每个类的对象进行整体排序(使用类实现这个接口,在类中去重写里面的comparTo方法,再通过实例化的时候,调用Collections.sort()方法传入包含对象的集合或者数组就会进行排序)

称为自然排序,类的comparTo方法称为自然排序方法
第一步:定义要比较的类,实现Comparable接口
第二步:重写comparTo方法
第三步:测试 (Collection.sort(包含用比较类实现的对象的集合))

Comparator 和Comparable的区别:

在这里插入图片描述

泛型,<?extends 父类> 即可传入此父类下所有子类的类型
在这里插入图片描述
:接收的可以是Goods和Goods的子类
在这里插入图片描述
:接收的可以是Goods和Goods的父类

泛型作用,不用进行强制类型转换,避免运行时异常的安全隐患

自定义泛型类:
在这里插入图片描述
定义两个类型
在这里插入图片描述

在这里插入图片描述

自定义泛型方法

在这里插入图片描述

4. Java集合框架体系Map学习

4.1 什么是Map

1、也是一种容器,和前几天学习的有啥区别
2、API文档描述:将键映射到值的对象。一个映射(一个Map对象)不能包含重复的键;每个键最多只能映射到一个值
键(key)   : 本质就是一个数据
值(value)   : 本质也是一个数据
键值对: 就是一对(和两个是有区别的),一对一般是有某种关系

映射 : 上面说的一个映射就看成是一个Map对象

曾经的映射如下图:

在这里插入图片描述

3、小结: 什么是Map

Map也是一种容器的接口,里面存储的是一对一对的数据,每添加一次的时候添加的是两个(一对)数据
Collection体系,存储在都是单个单个的数据,数据之间没有关系的
Map和Collection是两个没有关系并列的体系(主要从代码结构来看)
Map的声明: public interface Map{}

4、Map的基本结构

Map 接口

  |--   TreeMap    : 判断重复的规则和TreeSet一样
TreeMap中的键(key)要么是具有自然排序能力;或者TreeMap中提供一
个比较器

  |--   HashMap   : 判断键是否重复和HashSet判断重复一样

4.2 Map的应用场景

1、 例如QQ的账号+密码:想象场景-需要使用一个集合搜集各位100人的QQ号码和密码;
2、 银行账户和密码
3、 游戏账号和密码
4、 搜集各位的姓名+女朋友的姓名 (情侣关系)
5、 坐标(x,y)
6、 ....

4.3 Map的中的重要方法

基本方法列表:==========================
1、 Object put(Object key,Object value);   如果当前添加的这个key已经存在了,会覆盖这个键之前的值,返回的是之前的value值
2、 boolean containsKey(Object key) 
3、 boolean containsValue(Object value) 
4、 Object get(Object key) ;    根据指定的键key找到对应的值,如果没有找到返回 null
5、 remove(Object key)  ;     删除指定key对应的那一对

重点方法列表:==========================
6、 Collection  values()   返回一个Map中的所有的value值
7、 Set keySet()    返回所有的key值的集合
8、 Set entrySet()  返回所有的entry对象
问题: 为什么第一个是返回Collection  二三个返回的是Set?
key   entry都是不能够重复的--- Set

4.4 Map的遍历方式
说明: 只考虑我们自己把放进去的key-value都一个一个拿出来
1、foreach 失败了!
原因:Map和Iterable没有任何关系

2、普通for/ while / do-while 失败
原因: Map中没有通过索引来获得数据的方法

3、迭代器 失败!
原因: ① Map没有实现Iterable接口就没有其中获得迭代器的方法;
② Map中也没有自己设计一个获得迭代器的方法

4、遍历方式一:
①先获得所有的key --》 set
② 遍历set ,通过调用Object get(Object key) 获得对应的value

Map m = new HashMap();
m.put("小明", 90);
m.put("小马", 60);
m.put("小郭", 60);
Set keys = m.keySet();
for (Object k : keys) {
	System.out.println(k+"<---->"+m.get(k));
}

5、遍历方式二:
① 得到所有的Entry对象 ,通过调用方法 Set entrySet();
② 遍历上面的entry 的集合,依次从每一个Entry对象中取出对应的key-value

Map m = new HashMap();
m.put("小明", 90);
m.put("小马", 60);
m.put("小郭", 60);
Set entrys = m.entrySet();
for (Object en : entrys) {
	// 需要把en强制转成 Entry类型
	Entry e = (Entry)en;
	System.out.println(e.getKey()+"--"+e.getValue());
}

5. Generic <泛型>

5.1 什么是泛型(体验)

// 准备一个List用来存储公司员工对象  假设有一个类 Employee
List  emp = new ArrayList();
emp.add(new Employee(“张三”));
emp.add(new Employee(“李三”));
emp.add(new Employee(“王三”));
由于List中可以存储任意类型的数据,因此可以这样
emp.add(“王麻子”);
emp.add(new Dog(“旺财”));
。。。

// 写一个发工资的方法
for(Object o : emp){
syso(“给”+o.getName() + 50000);
}

上面代码可能引发的问题: 当我们获得一个字符串 或者一条狗的时候可能就调用不出来getName()方法
结果: 从业务上来讲,emp集合中只应该放Employee类型的数据,但是List可以放任意的类型的数据,在编译的时候我们无法阻止

怎么办??? 使用泛型 —》限定我们上面的emp中只能够放Employee

List< Employee>  emp = new ArrayList< Employee>();

5.2 泛型类(接口)的设计
需求:设计一个点类Point,其中设计字段 x y;
问题:里面的字段x y 使用什么类型好呢? double int 。。。
效果:需要设计上面的类,满足不同的人的需求,有些希望使用double int…

class Point{
    double x;
    double y;
}  

class Point{
    int x;
    int y;
}  

。。。。

一个类本质看成是一个模板,然后希望是一个通用的模板:

class Point{
    数据类型 x;
    数据类型 y;
}  

希望在设计类的时候,其中的数据类型我们就写一个符号,泛指所有的类型,但是不指具体的某种类型
当有人使用我们上面的模板来创建一个对象的时候他们自己可以指定自己的类型

怎么做:

class Point<数据类型>{    // 表示在类声明了一个符号  数据类型,是一种泛指
    数据类型 x;
    数据类型 y;
}  

规范的写法应该是使用一些字母(常见的字母):

E    Element  元素
T    Type    类型
K	 Key     键
V    Value   值

也可以支持多个泛型参数例如Map<K,V>

总结

在这里插入图片描述

在这里插入图片描述

补充(Iterator迭代器)

Iterator(迭代器):

Iterator接口可以以统一的方式对各种集合元素进行遍历
hasNext()方法检测集合中是否还有下一个元素
next()方法返回集合中的下一个元素

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38846837/article/details/84944784