java自学之路-day12

JAVA12

集合框架

介绍

l  是一种容器可以用来存储多个数据

l  数组不可变 集合可变

l  集合中存储的是引用类型

ArrayList回顾

存储int类型

l  不接收基本类型但是java1.5后有自动装箱和自动拆箱能将int类型自动转换为包装类型

存储自定义类对象 引用类型

l  自定义类重写了Object类的toString方法

l  向集合中添加了对象后

l  遍历输出的集合里面的不再是对象内存地址 而是重写了的toString方法的格式输出

l  toString 可以用工具直接生成 也可以自定义


集合学习目标

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

l  必须使用集合存储对象

l  遍历集合 去除对象

l  集合自己的特性 ArrayList是一个可变数组

集合继承关系图

l  查询API

l  所有集合在Java.util包中

l  以ArrayList为例

  1. 继承了抽象类 实现了接口 List

l  关系图

 

  1. Set接口 集
  2. LinkedList 链表
  3. LinkedHashSet 基于链表的哈希表实现
  4. List 和Set 存储方式不一样
  5. 由于细节不同 共性相同 因此从共性的功能父类接口学习入手

Collection接口

概述

l  集合中的根接口 它定义的方法所有子类实现类可以使用

l  代表一组对象

l  一些允许重复的元素存在 List

l  一些不允许重复的元素存在 Set

l  一些是有序的 List

l  一些事无序的 Set

Collection接口中的方法

l  add()

l  clear()

  1. void clear()
  2. 清空集合中的所有元素
  3. 使用接口多态调用 新建集合对象
  4. 示例

 

  1. 有序集合

 

  1. 只是清空集合 不是销毁集合

 

l  Contains()

  1. bollean contain(Object o)
  2. 判断任意对象是否存在于集合中
  3. 对象存在返回true
  4. 示例

 

  1. 如果

 

运行是false

应为123是integer “123”是String

l  Size()

  1. 三种长度表现

数组 length 是属性 返回值是int

字符串 .length() 方法 返回值是int

集合 .size()  方法

l  toArray

  1. 把集合中的元素转为为一个数组中的元素
  2. Object[] toArray()
  3. 返回值是一个存储对象的数组 存储的类型是Object
  4. 示例

 

  1. 数组不可变
  2. 意义

例如获取文件夹中的内容 获取需要集合 最终需要数组

l  Remove()

  1. boolean remove(Object o) 
  2. 如果有重复元素 只会删除一个
  3. 删除成功返回true 否则 false

iterator()迭代器接口

l  概述

  1. Java中有很多集合 集合容器不一样 存取方式不一样
  2. 为了方便统一存取 定义了迭代器
  3. 每一个集合一种通用的获取方式
  4.  

 

  1. 为了进行遍历集合的

l  实现原理

娃娃机

l  抽象方法

  1. boolean hasNext()
  2. 如果仍有元素可以迭代,则返回 true。
  3. next()
  4. 返回迭代的下一个元素。
  5. 实现类

iterator   英 [ɪtə'reɪtə]

a)         Collection有一个方法是

  1. Iterator<E>  iterator()  E是Collection中的类型参数

b)         Collection 的方法是实现了接口 Iterable 的Iterator<T> iterator() 

c)         这个方法返回的是一个在此 collection 的元素上进行迭代的迭代器。也就是一个Iterator接口的实现类的对象

d)         然后就可以用这个实现类的对象引用进行调用方法

e)         也就可以对集合进行遍历或者说叫迭代

f)          示例

 

 

通用遍历模式 hash也可以

 

l  执行过程

  1. 调用iterator方法运行后集合内部就会产生一个指针
  2. 指针指向-1位
  3. While循环 hasNext判断有没有元素
  4. 有元素 就执行 Next方法 指针移动指向这一个元素
  5. 直到下一个没有元素 指针指向 空 返回false
  6. 不写next 指针不会动 会进入死循环
  7. 如果循环完毕 再次执行 next  会报没有元素异常
  8. 循环完毕指针不会返回 所以迭代器只能执行一次
  9.  

 

  1. For循环迭代

 

节省内存

集合迭代中的转型

l  集合不指定存储的数据类型

l  集合什么都能存

l  迭代器获取 也不能加类型

l  next取出的是Object类型

l  输出的也是Object类型

l  如果需要输出不同类型的特有属性就Object需要向下转型 在调用

增强For循环 JDK1.5后的新特性

l  引入

  1. 出现了一个新接口Iterable
  2. Collection不在是总的接口
  3. 在java.lang包中
  4. 实现一个增强的for循环
  5. 实现这个接口允许对象成为foreach语句的目标
  6. 数组 和所有集合都可以使用增强for

l  格式

  1.  

 

  1.  

 

 

  1.  

 

a)         i相当于只是可以进行赋值的指针

b)         只是轮换赋值和数组中的元素没有关系

  1. 优点

a)         代码少了 方便对容器进行遍历

  1. 缺点

a)         没有索引不能操作容器里面的元素

  1.  

 

l  练习

  1. 遍历集合 集合存储引用类型
  2. 只做遍历 可以用 要是需要操作数据比如 排序 查找 等就不行

 

  1. 可以进行调用引用类型的方法

泛型

引入

l  示例

  1. 不写泛型的集合

 

  1. 输出字符串长度需要强转

此时在输入其他类型比如 1 integer类型

输出就会报异常

出现安全问题

所以引入了泛型

 

  1.  

 

定义和使用

l  Jdk1.5 出现安全机制 保证程序的安全性

l  指明了集合中的存储数据的类型<数据类型>

l  解决了安全问题

l  不需要强转 减少了代码量

l  可以使用增强for

伪泛型

l  只是编译手段

l  符合类型编译失败

l  不符合类型编译成功

l  编译后的文件里没有泛型

l  真泛型 c++

带有泛型的类

l  例如ArrayList类

  1. java.util
    类 ArrayList<E>  
  2. <E>就是泛型
  3. Element 元素 实际思想就是一个变量
  4. E写数据类型 String Integer

 

l   

 

泛型的方法

l  add()

  1. 带泛型的方法
  2. boolean add(E e) 
  3. E跟着类的E同步

l  <T> T[]

 toArray(T[] a)

  1. 传递的数组类型和类的E相同
  2.  

 

泛型的接口

l  java.util
接口 List<E>

  1. 实现类先实现接口 不理会泛型
  2.  

 

l  实现类实现接口的同时指定了数据类型

  1.  

 

泛型的优点

l  保证了在强行转换时安全问题

l  避免了强转

l  把错误由运行提前到了编译

l  带来了增强For

l  必须是jdk1.5后

l  Jdk1.4没有泛型 只能靠程序员自己解决

泛型的通配符

l  Dos通配符 del s.*    *就是通配符

l   同时迭代两个集合

l  参数类型应该写共同实现的接口或父类

数据类型泛型应该写 通配符 ?

l  迭代器数据类型也应该写 ?

  1.  

 

 

 

泛型的限定

l   

 

l   

 

List

特点

l  有序集合

l  取出时的顺序和存进去的顺序一样

l  具有索引 能精准控制位置

l  允许存储重复元素

l  实现类 ArrayList满足以上特点

抽象方法

l  List带索引的方法是特有方法

l  Boolean add(E e)

  1. 向列表尾部添加指定的元素
  2. 和collection接口一样

l  void add(int Index,E)

  1. 将元素插入到列表的指定索引上
  2. 无返回值
  3. Java.awt.List
  4. Java.util.List 是我们学习的包
  5. 不能超过两位集合索引进行添加 可以超过一位集合索引进行添加

 

  1. 否则会索引越界异常

 

分别是索引越界异常

数组越界异常

字符串越界异常

l  E remove(int index)

  1. 移除指定索引的元素
  2. 不能超过索引删除
  3. 返回删除之前的元素

l  Boolean remove(object)

  1. 返回布尔值
  2. 从列表中移除第一次出现的指定元素
  3. 和父接口Collection一样

l  E Set(int index, E )

  1. 修改指定索引的上的元素
  2. 返回修改之前的元素
  3. 不能越界修改

迭代器的并发异常

l  不能在用迭代器遍历集合时,修改集合的长度

 

List存储数据的结构

 

l  List下有很多集合,他们所采用的结构方式是不同的,这样就导致了集合有各自的特点

供我们在不同的情况下使用

l  存储形式 常见得有 堆栈 数组 队列 链表 数组链表比较多 因为查询 修改比较多

l  堆栈

  1. 先进后出
  2. 手枪子弹仓

l  数组

  1. 查找速度快
  2. 连续的索引
  3. 增删速度慢

l  队列

  1. 先进先出
  2. 排队过安检

l  链表

  1. 增加删除速度快
  2. 查找速度慢
  3. 多个节点地址连接
  4. 自行车链条

 

 

ArrayList

自身特点

l  大小可变的数组实现

l  次实现不同步  线程不安全 执行速度快

l  里面有声明了一个Object数组elementData  什么都能存

l  在new ArrayList时构造方法可以指定数组的长度

l  Add 添加吧添加的元素放到数组里,并且调用一个方法用copyof进行扩容

l   空参时时默认10个元素大小的数组

l  因为是数组所以如果有查找需求就用ArrayList

LinedList

自身特点

l  List接口的链表实现

l  单向链表

l  增加删除速度快

l  大量首尾操作

特有方法

l  链表底层实现

l  addFirst(E) addLast(E)

  1. 添加到链表的开头
  2. 添加到链表的结尾

 

  1. 示例

a)         addLast(E)放到第一个语句 相当于add

b)         先写Last 后写 First 还是是先是First

l  E getFirst() Egetlast()

  1. 获取链表的开头和结尾
  2. 返回集合类型的一个元素
  3. 如果集合为空 就会没有元素异常
  4. 因此需要判断一下列表的size是否为0
  5. 或者判断一下is.Empty() 这个方法源码是判断了一下集合是否等于0
  6. Is.Empty()是父类Collection接口的方法

l  E removeFirst() E removeLast()

  1. 移除并返回移除的元素

Vecotor集合

特点

l  存储结构是数组

l  JDK当中最早的集合 JDK1.0

l  从JDK v1.2改进实现List 接口

l  是同步 线程安全 运行速度慢

l  已被ArrayList取代

l  和ArrayList方法差不多

l  区别

  1. 方法

 

  1. addElements 相当于add
  2. elements 返回此向的枚举 相当于跌倒器
  3. has和next相当一迭代器的has和next
  4. 1.2出现后

Set接口

介绍

l  不允许存储重复元素

l  取元素只能采用 迭代器和增强For

l  不能使用索引相关的方法

l  方法和Collection一样

HashSet

介绍

l  此类实现了set接口

l  有哈希表支持

l  实现实际是一个Map集合

l  构造器new 的时候实际上是new了一个map集合

l  取元素不保证存的顺序 无序集合

l  不保证顺序永远不变

l  不存储重复元素

存储和迭代

l  和ArrayList代码编写完全一致

l  示例

  1. 迭代器

 

 

  1. 增强For
  2. 不存储重复元素

 

 

哈希表的数据结构

 

l  存储取出比较快

l  线程不安全 运行速度快

l  哈希表的解释图

 

 

  1. 链表数组结合体
  2. 数组存储的是一个个链表
  3. 桶比喻链表的数量
  4. 初始容量表示数组的容量
  5. 加载因子是数组长度的百分比
  6. 初始容量默认是16
  7. 加载因子默认是0.75  16*0.75
  8. 初始容量和加载因子都可以设置
  9. 当桶占数组的12个时 数组会扩容一倍 即数组复制
  10. 数组复制很难占用内存资源
  11. 加载因子太大 需要扩容时太慢
  12. 加载因子太大 会频繁扩容
  13. 数组扩容叫做数组的再哈希

字符串对象的哈希值

l  来源于父类Object

l  对象的哈希值是十进制整数

l  HashCode所有类都可以有

l  是个本地方法没有源码

l  哈希值不确定

l  可以被子类重写

l  存储在HashSet的依据

l  String重写了HashCode方法

  1.  

 

  1. hash是String源码中定义的默认是0

 

  1. 因此hashcode和字符串每个元素的Ascii值有关 因此同一个字符串hashcode一样

哈希表的存储过程

l  可以存储null

l  代码

 

l  图

 

  1. 先调用hashCode查询对象哈希值
  2. 如果没有这个哈希值就存储这个对象
  3. 如果又来一个 再次调用hashCode查询对象的哈希值
  4. 这个哈希值和上一个一样
  5. 此时会调用后来的对象调用equals方法和第一个进行比较
  6. 结果为true 并且两个对象哈希值一样 
  7. 因此哈希表判断出这个元素已经重复
  8. 如果前5部一样,第6步的结果是false
  9. 会采用桶的方式进行存储
  10. 源码在HashMap  put方法中

哈希表存储自定义对象

l  可以存储属性值相同的两个不同对象

l  为避免重复需要自定义对象重写hashCode和equals方法

l  参考String的算法

l  name.hashCode()+age

l  姓名年龄不同hashcode相同

l  因此还需要重写equals

 

l  hashCode巧合相同太多 总调用equals效率太低

l  因此需要修改hashcode方法 修改该会降低hashcode相同的概率

 

不要乘1和零其他的都会降低概率

l  但不是绝对的 String乘以31还是有

 

l  可以alt shift s可以自动生成

LinkedHashSet

介绍

l  具有可预知迭代顺序

l  具有顺序存储和取出的顺序一样

l  双向链表

l  线程不安全的集合运行速度快

l  不允许重复

ArrayList和HashSet判断对象是否重复

ArrayList是否重复

l  用父类contains方法进行判断

l  该方法依赖于equals方法

l   

 

 

HashSet是否重复

l  Add

l  Contains 依赖于equals

其他

l  只要放入集合就要考虑重写equals和hashCode

l  八种数据类型和基本类型包装类型都重写了这两个方法

l  避面重复性

面试题

两个对象

哈希值相同

equals返回值一定是true吗

正确答案:不一定

两个对象

如果equals方法返回true

哈希值一定相同吗

正确答案:一定

初步分析

 

l  题目一

  1. 重写了两个方法

 

 

  1. 证明了题目一 答案是不一定的

l  题目二

  1. 重写了方法

 

  1. 证明了题目二的答案也是不一定的

进一步分析

l  在Object类的hashCode 中Sun公司对此有规定

 

l  返回哈希码值能有效的避免哈希表内的属性相同的重复对象元素,从而降低哈希表的运算和存储压力,提高了哈希表的性能

l  返回的哈希值必须一定 否则会违反第一项协定 比如题目二的更改后的 a+1

l  如果根据equals判定两个对象相等 哈希值必须一样 所以题目二 答案是正确的

l  如果两个对象不相等  哈希值不一定是真

l  Equals也有类似规定

 

转载于:https://www.cnblogs.com/DMYMaster/p/7203375.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值