黑马程序员技术交流社区
标题: 笔记 [打印本页]
作者: 庞帅 时间: 2018-4-14 23:20
标题: 笔记
第07天 集合
集合(HashSet, HashMap,Map集合嵌套):
一:set体系的特点
*set接口:
+继承自collection接口
+特点:
(1)元素无序(存入和取出的顺序不一致,但存入后每次取出的顺序都一样)
(2)元素不能重复(元素唯一)
(3)没有索引
注意:直接打印和获取元素都属于取出, 所以不要把打印当成是HashSet内部存储的样子
二:HashSet存储自定义对象并遍历
*HashSet类是set接口的实现类
+成员方法:
boolean add(E e): 添加成功true, 添加失败(重复了)返回false
1.HashSet保证元素唯一的原理:
+判断对象相同的两个方法:(HashSet且去重原理(简单版))
(1)hashcode()
如果判定哈希值不相同,则认为不重复
如果判定哈希值相同,则需要继续用equals()方法判断
(2)equals()
如果判定不相同, 则认为不重复
如果判定相同, 则认为重复
(1) HashSet的add()方法, 首先将新添加的元素和当前集合中的已有元素进行hash值比较, 依靠对象的"hashCode()"
(2) 如果hash值不一样, 则认为不重复, 直接添加新元素
(3) 如果hash值一样, 则继续与已有元素比较"地址值"或使用"equals()方法"进行比较
如果比较结果一样, 则认为重复, 不添加
如果和所有的已有元素比较都不一样, 则认为不重复, 添加元素
注意:自定义对象的hashCode()和equals()方法决定了该对象能否被去重
*hashCode()方法和equals()方法的优化
优化hashCode()方法, 即让该方法的返回值和成员属性相关联, 减少equals()的调用, 提高效率
(1)让hashCode()方法返回所有成员变量之和.
- 基本数据类型直接相加
- 引用数据类型获取该成员变量的hashCode方法返回值后再相加(boolean不能参与运算)
(2)优化equals方法
- 提高效率: this ==obj-->return true
- 提高向下转型的安全性:this.getClass() == obj.getClass()-->return false
三.Collections工具类
*Collection 和Collections 的区别
- Collection是接口, 是单列集合的顶层, 包含一些共性方法
- Collections是类, 提供操作Collection的一些工具方法, 类似的还有操作数组的Arrays工具类
*Collections类常用的静态方法:
(1) static int binarySearch(List list,T key):使用二分查找来查找元素在指定列表的索引位置 *(前提是集合已经排序,查找原理类似猜数字)
(2) static voidcopy(List dest, List src): 将源列表中的数据复制到目标列表 *(目标列表的长度至少等于源列表的长度)
(3) static voidfill(List list, Object obj): 使用指定对象填充指定列表的所有元素
(4) static voidreverse(List list): 反转集合中的元素
(5) static voidshuffle(List list): 随机打乱集合中元素的顺序
(6) static voidsort(List list): 将集合中的元素按照元素的自然顺序排序
(7) static voidswap(List list, int i, int j): 将指定列表中的两个索引进行位置互换
四:Map接口的概述
* Map<K, V>接口
是双列集合的顶层, 和Collection属于同级
+特点:
(1)存储方式是key-value(键值对)方式, 即一个键对应一个值
(2) 一个键只能映射一个值
(3) 键不能重复, 值可以重复
(4) 键是无序的
+Map和Collection的区别
- Map是双列集合, 用于处理有一一对应关系的数据,键不能重复且键无序
- Collection是单列集合, 有不同的子体系,List允许重复且有序, Set不允许重复且无序
五:Map功能概述和测试
*HashMap类
+多态创建对象: (也可以不使用多态)
-Map<K, V> map = new HashMap<>();
+常用方法:
- 增和改:V put(K key, Vvalue): 添加键值对.
注意: 如果key已经存在, 则会使用新的value覆盖原有value,并将原有value返回
- 删:
void clear(): 清空集合
V remove(Object key): 删除指定键的值(key和value都会删除)
- 查:
-V get(Object key): 通过指定键获取值
- int size(): 获取集合长度
- 判断:
-boolean containsKey(Object key): 是否包含指定的键
-boolean containsValue(Object value): 是否包含指定的值
-boolean isEmpty(): 是否为空
- 遍历:
-Set<Map.Entry<K, V>> entrySet(): 获取键值对的Set集合
- Set<K> keySet(): 获取所有键的Set集合
-Collection<V> values(): 获取所有值得Collection集合
*Map的遍历方式
+ keySet()方法(Map的第一种遍历方式)
- 通过get(K key)方法获取key对应的value
+ entrySet()方法, 遍历值的集合(Map的第二种遍历方式)
- 使用Entry的getKey()获取key, 使用Entry的getValue()获取value
*注意:HashMap存储数据并遍历:String作为key时,相同的字符串内容会导致key重复,字符串通过equals比较返回true
自定义类的对象作为key, 是否重复取决于自定义对象的类中如何重写hashCode()和equals()方法
六:可变参数:
1.从JDK1.5开始
2.可变参数: 方法的形参可以传入不定数量个参数
3.定义格式: 形参数据类型... 形参名
注意事项:
1.可变参数的数量可以从0个到多个
2.可变参数只能是同一种数据类型
3.可变参数的定义位置必须在方法形参列表的最后一个
可变参数的原理:
底层是一个根据形参数量创建长度的数组, 通过JVM将形参转换为数组
如何使用可变参数?
1.在方法中使用: 把可变参数的形参名当做一个数组变量名, 遍历并获取元素
2.向方法中传入参数: 将多个参数值使用逗号分隔传入方法
七:Map嵌套演示: Map嵌套Map
Map<String, Map<String,String>>
理清key和value
- 存入: 先处理好内部的Map, 然后再放入外部Map
- 取出: 遇到Map就使用2种方式遍历即可
Map嵌套演示: Map嵌套Collection
Map<String,Collection<Student>>
理清key和value
- 存入: 先处理好内部的Collection, 然后再放入外部Map
- 取出: 遇到Map就使用2种方式遍历, 遇到Collection就用3种方式遍历
扩展:
让对象实现排序的2种方式
- 让对象具有自然顺序: 让JavaBean实现Comparable接口, 重写compareTo()方法
- 使用比较器: 定义一个类作为比较器, 实现Comparator接口, 重写compare()方法, 排序时传入该比较器实现类的对象
重写方法的返回值的作用:
- 返回值为负数: 则认为当前元素比被比较元素小
- 返回值为0: 则认为当前元素与被比较元素相等
- 返回值为正数: 则认为当前元素比被比较元素大
HashSet去重详细版原理
* 当调用HashSet的add()方法时,该方法内部调用的是一个HashMap的put()方法,将元素作为HashMap的key,存入HashMap中,
利用Map的key的唯一性,保证HashSet的元素唯一性
* 那HashMap的key如何保证唯一呢?
* 首先, HashMap的put方法, 会先计算key的hash值.
* 然后, 拿该hash值在一个名为table的Entry[]数组中寻找该hash值的索引.
* 之后, 在for循环的初始化条件中, 拿该索引值获取Entry[]数组中的Entry元素
* 如果没有该元素,即元素为null,说明元素不重复,则for循环不满足执行条件,直接略过for循环,并添加元素到Entry[]数组中,并在put()方法最后返回一个null
* 如果有该元素, 则进入for循环. 继续判断该元素是否与已有元素相同
* 首先,使用当前Entry集合中的每一个元素和新添加的元素进行hash值的比较
* 如果hash值不同, 则直接添加新的元素
* 如果hash值一样, 则比较Entry的key和传入的key是否相同或使用equals方法比较
*如果比较结果相同, 则认为是重复不添加, 且返回已有元素
*如果不重复, 则继续for循环比较下一个
*直到所有比较结果都不相同, 则认为不重复, 添加新的元素
第08天 异常
一:异常的体系结构:
Throwable(最顶层)
Error:不能处理的异常
Excrption:可以处理的异常,编译异常
RuntimeExcrption:运行异常,编译正常
二:jvm处理异常的方式:
1.将异常的类型,原因还有位置显示在命令行,并且终止程序
三:异常的处理方式:
捕获处理
try..catch语句
try{
有可能出现问题的代码
} catch(异常类型 类型名){
处理异常;
}
try..catch的执行顺序:
首先执行try语句,如果有异常直接调到catch语句中,整个try..catch语句结束,
如果没有异常,try..catch语句不执行
抛出去:
当不想或不能解决异常时,可以使用关键字throws在方法声明处将异常抛出,谁调用方法谁处理
四:多异常处理:
1.可以使用多个try.. catch语句
2.使用一个try和多个catch
多异常执行顺序:
1.多个catch之间可以有子父类关系
2.平级或同级没有子父类关系
3.如果有子父类,父类必须放到后面
五:Throwable的常用方法:
(1):1.StringgetMessage():异常原因
2.String toString():异常类型和原因
3.void printStackTrace():异常类型,原因和位置
*该方法只是将异常信息以System.err错误输出流打印到控制台,并不会结束程序
*System.err.println:输出的是红字
(2)finally:组合try。。catch使用,用于释放资源等收尾工作,无论try..catch是如何执行,
finally的代码块中的代码都会执行。
try{
有可能出现问题的代码
} catch(异常类型 类型名){
处理异常;
}finally{
释放资源;
清理垃圾;
}
六:异常的分类:
1.运行时期异常:RuntimeExcrption的子类就是运行时期异常,在编译时期可以自由选择处理或不处理。
2.编译时期异常:是Excrption的子类,非RuntimeExcrption的子类在编译时期必须处理,
七:自定义异常:
1.throws:处理异常的一种方式,把异常抛出,有调用者处理
2.throw:制造异常的方式,并且结束方法
*注意:如果是抛出的编译时期异常,必须在方法声明处抛出
*写一个类去继承Exception或RuntimeException,然后实现多个构造即可
八:递归:
1.概述:
(1) 把大问题拆成小问题
在方法本身不断调用方法自己
(2)注意事项:
递归一定要有出口,内存溢出
递归次数不宜过多,内存溢出
九:斐波那契列数:
不死神兔 :第一个月和第二个月都是一对兔子,第三个月生下一对兔子,以后每月都生一对兔子,
即:1--1
2--1
3--2
4--3
5--5
6--8
7--13
.
.
.
20
从第三个月开始:每个月都是前两个月兔子之和,即n=(n-1)+(n-2);
| 欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |