【Java笔记】基础学习笔记汇总(上)
- 【Java笔记】基础学习笔记汇总(上)
- 1. 字节和位
- 2. JDK/JRE/JVM的关系
- 3. 标识符
- 4. 字符串常量和字符常量
- 5. 基本数据类型 (4类8种)
- 6. 数据类型转换
- 7 .常用的ASCII码
- 8. 算数运算
- 9. 逻辑运算符的短路
- 10. 三元运算符
- 11. 重载
- 12. 初始化数组的格式
- 13. 各类型初始化值
- 14. Java的内存需要划分为5各部分
- 15. 面向对象的三大特性
- 16.创建类
- 17. 局部变量和成员变量
- 18. 构造方法
- 19. Scanner类
- 20. 匿名对象
- 21. Random类
- 22. 泛型
- 23. ArrayList
- 24. 包装类
- 25. 字符串 String类
- 26. Static关键字
- 27. 静态代码块
- 28. 工具类java.util.Arrays
- 29. 工具类java.util.Math
- 30. 继承是多态的前提
- 31. 区别子类方法中重名的三种变量
- 32. 重写(Override)和重载(Overload)
- 33. 权限修饰符
- 34. 继承关系中,父子类构造方法的访问特点
- 35. super关键字和this关键字
- 36. 抽象类和抽象方法
- 37. 接口
- 38. Java8开始,接口里允许定义默认方法
- 39. Java8开始,接口里允许定义静态方法
- 40. Java9开始,接口里允许定义私有方法
- 41. 接口中定义”成员变量“
- 42. 使用接口的注意事项
- 43. 接口之间的多继承
- 44. 多态
- 45. 对象的向上转型,其实就是多态的写法
- 46. 对象的向下转型
- 47. 判断对象是不是某个类 instanceof
- 48. final关键的使用
- 49. 内部类
- 50. 成员内部类
- 51. 定义一个类时,权限修饰符规则
- 52. 局部内部类
- 53. 匿名内部类
- 54. 工具类java.util.Date
- 55. 抽象类java.text.DateFormat
- 56. DateFormat的子类java.text.SimpleDateFormat
- 57. 抽象类java.util.Calendar
- 58. System类
- 59. java.lang.StringBuilder类 和 String类
- 60. Java1.5之后的新特性:自动装箱和自动拆箱
- 61. 基本数据类型与字符串之间的转换
- 62. java.util.Collection集合接口的框架介绍
- 63. java.util.Collection接口和单列集合的共性方法(7个)
- 64. java.util.Iterator迭代器接口
- 65. JDK1.5以后出现的 增强for循环(for each)
- 66. 泛型
- 67. 使用和定义含有泛型的 类/方法/接口
- 68. 泛型的通配符: ?
- 69. 集合工具类Collections中的静态方法 .shuffle(...)
- 70. java.util.list 接口 extends Collection
- 71. ArrayList集合,是多线程,底层用的是数组
- 72. LinkedList集合,是多线程,底层用的是链表结构
- 73. Vector集合,是单线程,底层用的是数组,是JDK1.0最早期的集合
- 74. java.util.Set 接口 extends Collection
- 75. java.util.HashSet集合 implements Set
- 76. 哈希值/JDK里的哈希表结构
- 77. Set集合存储元素不重复的原理
- 78. java.util.LinkedHashSet集合 extends HashSet集合
- 79. JDK1.5之后出现的 可变参数
- 80. 集合工具类 java.utils.Collections
- 81. java.util.Map< k, v >集合
- 82. Map集合遍历的两种方式
- 83. java.util.HashMap< k, v >集合 implements Map< k,v >接口
- 84. java.util.LinkedHashMap< k,v >集合 extends HashMap< k,v >
- 85. java.util.HashTable< k, v >集合 implements Map< k,v >接口
- 86. 遍历String字符串,获取每一个字符(两种方法)
- 87. JDK9 在List、Set、Map接口中的新特性:静态方法 of
【Java笔记】基础学习笔记汇总(上)
原本笔记都是手写的,为了之后方便保存和查阅,还是下定决心,把他敲出来正好作为一篇博客的内容。也借这个机会,好好的复习一遍Java基础知识。这是上半部分。
自学材料:黑马程序员Java全套视频
1. 字节和位
位(bit):一个数字0或1
字节(byte):8位一字节,这是数据存储中的最小单位
1Byte = 8bit
1KB = 1024Byte
2. JDK/JRE/JVM的关系
- JRE(Java Runtime Environment)
Java程序运行时的环境,包含 JVM 和 核心类库
- JDK(Java Development Kit)
Java程序开发工具包, 包含 JRE 和 开发人员使用的工具
想要运行一个Java程序,只需要安装JRE;想要开发一个Java程序,必须安装JDK
结构:
- JDK
- 编译等开发工具
- JRE
- 运行类库
- JVM
3. 标识符
指在程序中,我们自己定义的内容。比如类的名字、方法的名字和变量的名字等等
命名规范:
1)类名规范:
首字母大写,后面的每个单词的首字母大写(大驼峰式)
2)变量名规范:
首字母小写,后面每个单词首字母大写(小驼峰式)
3)方法名规范:
同变量名
4. 字符串常量和字符常量
字符串常量:凡是用双引号引起来的部分。“abc”
字符常量:只是用单引号引起来的单个字符。‘A’
5. 基本数据类型 (4类8种)
整数:byte short int long
浮点:double float
字符:char
布尔:boolean
6. 数据类型转换
byte、short、char这三种类型在运算的时候,都会被首先提升为int类型,然后再计算
7 .常用的ASCII码
‘0’ :48
‘A’ :65
‘a’ :97
8. 算数运算
一旦运算当中有不同数据类型的数据,那么结果将会是数据类型范围大的那种
- 对于 ++ 和 –
- 前++:那么变量立刻马上+1,然后拿着结果进行使用
- 后++:那么首先使用变量本来的数值,然后再让变量+1
- –类型 类似
9. 逻辑运算符的短路
与&&和||
如果根据左边可以判断得到最终结果,那么右边的代码将不执行
10. 三元运算符
格式:
数据类型 变量名称 = 条件判断 ? 表达式A True :表达式B False
注意事项:
- 必须同时保证表达式A和表达式B都符合左侧的数据类型的要求
- 三元运算符的结果必须被使用
11. 重载
- 方法重载与下列因素有关
- 参数个数不同
- 参数类型不同
- 参数的多类型顺序不同
- 重载与下列因素无关
- 与参数的名称无关
- 与方法的返回值类型无关
12. 初始化数组的格式
- 动态初始化数组的格式:
数据类型[] 数组名称 = new 数据类型[长度]
- 静态初始化数组的格式:
数据类型[] 数组名称 = new 数据类型[] {元素1,元素2,。。。}
数据类型[] 数组名称 = {元素1,元素2,。。。}
13. 各类型初始化值
使用动态初始化数组的时候,元素会被自动拥有一个默认值
- 整数类型 0
- 浮点 0.0
- 字符 ‘\u0000’
- 布尔 false
- 引用 null
14. Java的内存需要划分为5各部分
1)栈
存放的都是方法种的局部变量。方法的运行一定要在栈中运行
作用域:一旦超过作用域,立刻从栈内存中消失
2)堆(Heap)
凡是new出来的东西,都在堆中
堆内存中的东西都有一个地址值:16进制
3)方法区(Method Area)
存储 .class 的相关信息,包含方法的信息
4)本地方法栈
5)寄存器
例如以下分析:
15. 面向对象的三大特性
面向对象的三大特性:封装、继承、多态
16.创建类
定义类时,成员方法不要static关键字
创建类,格式: 类名称 对象名 = new 类名称( )
17. 局部变量和成员变量
当方法的局部变量和类的成员变量重名时,根据”就近原则“,优先使用局部变量
如果在方法中需要访问本类中的成员变量,使用的格式:this.成员变量名
18. 构造方法
格式:
public 类名称 (参数类型 参数名称,。。。){方法体}
注意:
- 如果没有编写任何的构造方法,编译器会默认给一个构造方法
- 构造方法是可以进行重载的
19. Scanner类
- 创建
Scanner sc = new Scanner(System.in)
- 使用
1)获取键盘输入的一个int数字
int num = sc.nextInt();
2)获取键盘输入的一个字符串
String str = sc.next();
20. 匿名对象
只有右边的对象,没有左边的名字和赋值运算符
形如:
new Person().name = “xxx”;
new Person().showName();
注意:
- 匿名对象只能使用唯一的一次,下次再用不得不在创建一个新的对象
21. Random类
用来生成随机的数字
- 创建
Random r = new Random();
- 使用
1)获取一个随机int数字(范围是int 的所有范围,有正负两种):
int num = r.nextInt();
2)获取一个随机的int数字(参数代表了范围,左闭右开区间):
int num = r.nextInt(3); // 表示[0,3),也就是0到2
22. 泛型
也就是装在集合中的所有元素,全都是统一的什么类型
注意:泛型只能是引用类型,不能是基本类型
23. ArrayList
从JDK1.7开始,创建ArrayList时的右侧尖括号<> 内不用写泛型
常用方法:
1)添加数据:.add()
2)获取数据,参数是索引:.get(int index)
3)删除元素,参数是索引号,并返回对应位置的元素:.remove(int index)
4)获取集合的长度:.size()
注意:
如果希望向集合ArrayList当中存储基本类型数据,必须使用基本类型的包装类
24. 包装类
基本类型 包装类(引用类型,包装类都位于java.Lang包下)
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
注意:
从JDK1.5开始,支持自动装箱/拆箱
25. 字符串 String类
字符串效果上相当于char[]字符数组,但是底层原理是Byte[]字节数组
- 创建字符串的常见3+1种方式
- 三种构造方法
- public String()
- public String(char[] array):根据字符数组的内容,创建字符串
- public String(byte[] array):根据字节数组的内容,创建
- 直接创建:String str = “Hello”;
对于基本数据类型来说:”==“ 是进行数值的比较
对于引用类型来说:”==“是进行地址值的比较
String类的常用方法
1)比较字符串的内容是否相同(两种)
- .equals(…)
注意:如果比较双方一个常量,一个变量,推荐把常量字符串写在前面,防止空指针异常。
- .equalsIgnoreCase(…):忽略大小写进行比较
2)字符串操作的方法
- .length():字符串的长度
- .concat(String str):拼接字符串,返回新的字符串
- public char charAt(int index):获取指定索引位置的单个字符(索引从0开始)
- public int indexOf(String str):找到参数字符串在本字符串中首次出现的索引位置,如果没有返回-1值
3)字符串的截取方法
- .substring(int index):截取从参数位置到字符串末尾,返回新字符串
- .substring(int begin,int end):截取从begin开始,到end结束。
- 注意:[begin,end):包含左边,不包含右边
4)字符串转换的方法
- .toCharArray():转化为字符数组,返回
- .getBytes():获取当前字符串底层的字符数组
- public String replace(CharSequence oldString, CharSequence newString):将字符串中的老字符串替换为新的字符串,返回
5)分割字符串
- public String[] split(String regex):根据regex,将字符串切分成若干个部分
- regex:是正则表达式
26. Static关键字
用了Static关键字以后,里面的内容不再属于对象自己,而是属于类的,所以凡是本类的对象,都共享同一份
- 一旦使用static修饰成员方法,那么这就成为了静态方法。静态方法不属于对象,而是属于类
- 对于静态方法来说,最好通过类名称来调用;而且不需要创建对象就可以直接通过类名称来调用
总结:无论是成员变量,还是成员方法,如果有了static,都推荐使用类名称进行调用
例如:
类名称.静态变量
类名称.静态方法()
注意:
- 静态不能访问非静态
- 静态方法中不能用this
27. 静态代码块
格式:
public class 类名称{
static{//静态代码块的内容}
}
特点:
- 当第一次用到本类的时候,静态代码块执行唯一的一次
- 静态内容总是优先于非静态,所以静态代码块比构造方法还要先执行
静态代码块的典序用途:
- 用来一次性的对静态成员变量进行赋值
28. 工具类java.util.Arrays
与数组相关的工具类
1)public static String toString(…):将数组变成字符串
使用:Arrays.toString(…)
2)public static void sort(…):对数组元素进行排序
注意:
- 如果是数组数组,默认升序,从小到大
- 如果是字符串,按照字母升序
- 如果是自定义类型,那么自定义的类需要有Comparable或Comparator接口的支持
29. 工具类java.util.Math
与数学运算有关
- Math.abs(double num)
- Math.ceil(double num):向上取整
- Math.floor(double num):向下取整
- Math.round(double num):四舍五入
- Math.PI:近似圆周率常量
30. 继承是多态的前提
如果没有继承,就没有多态
继承主要解决的问题就是:共性抽取
31. 区别子类方法中重名的三种变量
- 局部变量:直接写成员变量名
- 本类的成员变量:this.成员变量名
- 父类的成员变量:super.成员变量名
32. 重写(Override)和重载(Overload)
- 重写:方法的名称一样,参数列表 也一样
- 重载:方法的名称一样,参数列表 不一样
注意:
1)方法的覆盖重写的特点:创建的是子类对象,则优先用子类的方法
2)子类方法的返回值必须小于等于父类方法的返回值范围
3)子类方法的权限必须大于等于父类方法的权限修饰符
33. 权限修饰符
public > protected > (default) > private
34. 继承关系中,父子类构造方法的访问特点
1)子类构造方法中有一个默认隐含的”super()“调用,所以一定是先调用父类的构造,后执行子类的构造
2)子类的构造可以通过super关键字来调用父类的重载构造
3)super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super()
总结:
子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super()调用。super()只能有一个,还必须是第一个
35. super关键字和this关键字
super关键字的三种用法:
- 在子类的成员方法中,访问父类的成员变量
- 在子类的成员方法中,访问父类的成员方法
- 在子类的构造方法中,访问父类的构造方法
this关键字的三种用法:
- 在本类的成员方法中,访问本类的成员变量
- 在本类的成员方法中,访问本类的另一个成员方法
- 在本类的构造方法中,访问本类的另一个构造方法
注意:
1)this(…)调用也必须是构造方法的第一个语句,唯一一个
2)super和this两种构造调用,不能同时使用
36. 抽象类和抽象方法
1)
抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束
抽象类:抽象方法所在类,必须是抽象才行。在class之前写上abstract即可
2)如何使用抽象类和抽象方法
- 不能直接创建new抽象类对象
- 必须先用一个子类来继承抽象父类,子类必须重写抽象父类中的抽象方法
- 创建子类对象进行使用
3)抽象类使用的注意事项
- 抽象类不能创建对象,只能创建其非抽象子类的对象
- 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用
- 抽象类中,不一定含有抽象方法,但是有抽象方法的类必定是抽象方法
- 抽象类的子类,必须重写抽象父类的所有的抽象方法,除非该子类也是抽象类
37. 接口
就是多个类的公共规范
1)
Java7,接口包含:1.常量、2.抽象方法
Java8,额外包含:3.默认方法、4.静态方法
Java9,额外包含:5.私有方法
2)定义抽象方法
格式:
public abstract 返回值类型 方法名(参数列表);
注意:
- 接口中的抽象方法,修饰符必须是两个固定的关键字:public abstract
- 这两个关键字修饰符,可以选择性的省略
3)实现类必须重写接口中所有的抽象方法,除非实现类是抽象类
38. Java8开始,接口里允许定义默认方法
用来解决接口升级的问题
格式:
public default 返回值类型 方法名称(参数列表){方法体}
注意:
- 接口的默认方法,可以通过接口的实现类的对象,直接调用
- 接口的默认方法,也可以被接口的实现类进行覆盖重写
39. Java8开始,接口里允许定义静态方法
格式:
public static 返回值类型 方法名称(参数列表){方法体}
用法:通过接口名称,直接调用其中的静态方法;格式:接口名称.静态方法名(参数);
40. Java9开始,接口里允许定义私有方法
只有接口自己才能调用,不能被实现类或别人调用
1)普通私有方法,解决多个默认方法之间的重复代码问题
格式:
private 返回值类型 方法名称(参数列表){方法体}
2)静态私有方法,解决多个静态方法之间重复代码问题
格式:
private static 返回值类型 方法名称(参数列表){方法体}
41. 接口中定义”成员变量“
必须使用 public static final 三个关键字进行修饰
格式:public static final 数据类型 常量名称 = 数据值;
注意:
- 接口中的常量,可以省略public static final关键字
- 接口中的常量,必须进行赋值,不能不赋值,一旦赋值就不能gaib
- 接口中的常量的命名规则:使用完全大写的字母,用下划线进行分割
42. 使用接口的注意事项
1)接口是没有静态代码块或者构造方法的
2)一个类的直接父类是唯一的;但是一个类可以同时实现多个接口
3)如果实现类所实现的多个接口中,存在重复的默认方法,那么实现类必须对冲突的默认方法进行重写
4)一个类如果直接父类中的方法和接口中的默认方法产生冲突时,优先用父类中的方法
43. 接口之间的多继承
接口与接口之间可以是多继承
例如:public interface A extends B,C{…}
注意:
- 多个父接口中的默认方法如果重复,那么子接口必须进行默认方法的重写,而且要带着default关键字
44. 多态
1)
一个对象拥有多种形态,就是对象的多态性
即,【左侧】父类引用 指向【右侧】子类对象
格式:
父类名称 对象名 = new 子类名称(); 或者: 接口名称 对象名 = new 实现类名称();
2)多态情况下访问成员变量有两种方式:
- 直接通过对象访问成员变量:等号左边是谁,优先用谁,没有则向上找
- 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找
3)多态情况下,成员方法的访问规则:
- 看new的是谁,就优先用谁,没有则向上找
45. 对象的向上转型,其实就是多态的写法
格式:同多态的写法
含义:右侧创建的一个子类对象,把它当作父类来看待使用
注意事项:向上转型一定是安全的,从小范围转向大范围
弊端:对象一旦向上转型为父类,那么就无法调用子类原本特有的内容
解决方案:用对象的向下转型还原
46. 对象的向下转型
格式:子类名称 对象名 = (子类名称) 父类对象;
注意:向下转型的前提是保证对象本来创建的时候,就是这个子类的
47. 判断对象是不是某个类 instanceof
格式:对象 instanceof 类名称
返回的是布尔值
48. final关键的使用
常见的四种用法
1)当final关键字用来修饰一个类的时候
public final class 类名称{。。。}
含义:当前这个类不能有任何的子类(太监类);所有的成员方法都无法进行覆盖重写(因为没有子类)
2)当final关键字用来修饰一个方法时
这个方法就是最终方法,不能被覆盖重写
注意:对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾
3)当final用来修饰 局部变量,那么这个变量就不能进行更改
不变的含义:
- 基本数据类型,变量中的数据不变
- 引用类型,变量的地址值不可改变,但是内容可以改变
4)当final用来修饰 成员变量,这个变量也是不可变
- 成员变量必须手动赋值,不能再给默认值了
- 对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。二者选其一
- 必须保证类中的所有构造方法都会对final的成员变量进行赋值
49. 内部类
一个类内部包含另一个类
分类:
- 成员内部类
- 局部内部类(包含匿名内部类)
50. 成员内部类
定义格式:
外部类{
内部类{…}
}
注意:内用外,随意访问;外用内,需要内部类对象
1)使用成员内部类,有两种方式:
- 间接方式:在外部类的方法中,使用内部类,然后调用外部类的方法
- 直接方式,公式:
外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
2)内部类的重名变量访问
局部变量: num
内部类的成员变量: this.num
外部类的成员变量: 外部类名称.this.外部类成员变量名
51. 定义一个类时,权限修饰符规则
- 内部类:public / (default)
- 成员内部类:public / protected / (default) / private
- 局部内部类:什么都不能写
52. 局部内部类
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类
”局部“:只有当前所属方法才能使用它,出了这个方法外面就不能使用了
格式:
外部类{
外部类方法{
局部内部类{…}
}
}
局部内部类,如果希望访问所在的方法的局部变量,那么这个局部变量必须是【有效final的】
53. 匿名内部类
如果接口的实现类或父类的子类,只需要使用唯一一次,那么这种情况下就可以省略该类的定义,而改为使用匿名内部类。创建对象和调用方法的时候只能使用一次
匿名内部类的定义格式:
接口名称 对象名 = new 接口名称(){ //覆盖重写所有的抽象方法 }
54. 工具类java.util.Date
1)知识点
- 时间原点(0毫秒):英国格林威治的 1970年1月1日00:00:00;中国属于东八区,所以会加上8小时
- System.currentTimeMills():获取当前系统时间到时间原点的距离
- 1天 = 24*60*60 = 86400秒 = 86400 000毫秒
2)Date类的构造方法
- 空参构造:Date()
获取当前系统的日期和时间
- 带参构造:Date(long date)
参数:毫秒值;把毫秒值转化为Date日期
3).getTime() 方法
把日期转化为毫秒值;相当于System.currentTimeMills()
55. 抽象类java.text.DateFormat
作用:
- 格式化(日期 -> 文本)
- 解析(文本 -> 日期)
成员方法:
- String format(Date date)
- Date parse(String source)
DateFormat类是抽象类,无法直接创建对象使用,用DateFormat的子类java.text.SimpleDateFormat
56. DateFormat的子类java.text.SimpleDateFormat
构造方法:SimpleDateFormat(String pattern)
参数pattern:传递指定的模式
y 年;M 月;d 日;H 时;m 分;s 秒
例如:”yyyy-MM-dd HH:mm:ss“
注意:模式中的字母不能改变,连接模式的符号可以改变
- 把日期格式化为文本,例如:
new SimpleDateFormat(“yyyy-MM-dd”).format(new Date())
- 把文本解析为日期,例如:
new SimpleDateFormat(“yyyy-MM-dd”).parse(“2020-10-10”)
其中,如果字符串和构造方法的模式不一样,就会抛出ParseException异常
57. 抽象类java.util.Calendar
- 提供了日历字段:YEAR、MONTH、DAY_OF_MONTH、HOUR
- 其中有一个静态方法:getInstance():返回Calendar类的子类对象
- 常用的成员方法
- public int get(int field)
- public void set(int field,int value)
- public abstract void add(int field,int account)
- public Date getTime()
58. System类
1)public static long currentTimeMills()
返回以毫秒为单位的当前时间
2)public static void arraycopy(参数1,2,3,4,5)
静态方法,将数组中指定的数据拷贝到另一个数组中
参数:
- src:源数组
- srcpos:源数组中的起始位置(索引)
- dest:目标数组
- destpos:目标数组中的起始位置
- length:要复制的数组元素的数量
59. java.lang.StringBuilder类 和 String类
1)String类
字符串是常量,在创建之后不能改变
字符串底层是被final修饰的数组(private final byte[] value),不能改变,是一个常量
2)StringBuiler类:字符串缓冲区
可以提高字符串的操作效率。底层也是一个数组,但是没有被final修饰,可以改变长度。
初始容量为16(byte[] value = new byte[16])。如果超出容量,会自动扩容
3)构造方法:
- StringBuilder()
- StringBuilder(String str)
4)常用方法:
- public StringBuilder append(…);
添加任意类型数据的字符串形式,并返回
- public String toString()
把当前的StringBuilder对象转换为String对象
60. Java1.5之后的新特性:自动装箱和自动拆箱
61. 基本数据类型与字符串之间的转换
- 基本数据类型 -> String
1)基类 + ”“
例如:int i1 = 100; String s1 = i1 + “”;
2)包装类中的静态方法toString
static String toString(int i)
例如:Integer.toString(100);
3)String类的静态方法valueOf
static String valueOf(int i)
例如:String.valueOf(100);
- String -> 基本数据类型
使用包装类的静态方法parseXxx("…")
例如:Integer类:static int parseInt(String s)
62. java.util.Collection集合接口的框架介绍
63. java.util.Collection接口和单列集合的共性方法(7个)
所有单列集合最顶层的接口,里面定义了所有单列集合的共性方法(7个)
1)public boolean add(E e):添加元素到集合中
2)public boolean remove(E e):把给定的对象在当前的集合中删除
3)public boolean contains(E e):判断集合中是否包含给定的对象
4)public boolean isEmpty():判断当前集合是否为空
5)public int size():返回集合中元素的个数
6)public Object[] toArray():把集合中的元素,存储到数组中
7)public void clear():清空集合中所有的元素,但是不删除集合,集合还存在
64. java.util.Iterator迭代器接口
(对集合进行遍历)
接口中有两个常用的方法:
- boolean hasNext():判断集合中还有没有下一个元素,有就返回true,没有就返回false
- E next():返回集合中的下一个元素;把指针向后移动一位
- Iterator迭代器是一个接口,需要使用接口的实现类对象
- Collection接口中的 .iterator() 方法,返回迭代器的实现类对象
迭代器的使用步骤:
1)使用集合中的方法 .iterator() 获取迭代器的实现对象,使用Iterator接口来接收(多态);并且把指针(索引)指向集合的 -1 索引处
例如: Iterator< E > it = 集合名.iterator(); //其中,集合是什么泛型,迭代器是什么泛型
2)使用迭代器中的 .hasNext() 方法,判断有没有下一个元素
3)使用迭代器中的 .next() 方法 取出集合的下一个元素;并将指针向后移动一位
65. JDK1.5以后出现的 增强for循环(for each)
- 专门用来遍历数组和集合。
- 内部原理是个iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
66. 泛型
1)创建集合对象,不使用泛型:
- 好处:集合不使用泛型,默认类型就是Object类型,可以存储任意类型的数据
- 弊端:不安全,会引发异常
2)创建集合对象,使用泛型
- 好处:
- 避免了类型转换的麻烦,存储的是什么类型,取出就是什么类型
- 把运行期间的异常(代码运行之后抛出的异常),提升到了编译器(写代码的时候报错)
- 弊端:泛型是什么类型,只能存储什么类型的数据
67. 使用和定义含有泛型的 类/方法/接口
1)类
例如:
public class 类名 < E > {
private E name;
…
}
2)方法
泛型的定义在方法的修饰符和返回值类型之间
格式:
public <泛型> 返回值类型 方法名(参数列表){…}
例如:
public class …{
public < M > void method (M m){
…(m);
}
}
3)接口
两种使用方式:
- 在一个实现类实现一个接口的时候,指定泛型
- 创建对象的时候才确定泛型的类型
68. 泛型的通配符: ?
代表任意的数据类型
1)使用方式:
- 不能在创建对象的时候使用
- 只能作为方法的参数,传递数据类型时使用
2)通配符高级使用:受限泛型
- 泛型上限:< ? extends 类 >
只能接收该类及其子类
- 泛型下限:< ? super 类 >
只能接收该类及其父类
69. 集合工具类Collections中的静态方法 .shuffle(…)
- static void shuffle(List<?> list)
使用默认的随机源使得集合中的元素随机化
例如:Collections.shuffle(集合);
70. java.util.list 接口 extends Collection
list接口中几个Collection中没有,list中特有的方法
1)public void add(int index, E element):将指定的元素添加到该集合中的指定位置上
2)remove(int index):删除指定元素,并返回被移除的元素内容
3)public E set(int index, E element):用指定的元素替换集合中指定位置的元素,并返回被替换的元素值
4)get(int index)
遍历集合的3种方法:
- 普通for循环
- 使用迭代器
- 增强for循环
71. ArrayList集合,是多线程,底层用的是数组
增删元素,也是创建新的数组,所以也是查询快,增删慢
72. LinkedList集合,是多线程,底层用的是链表结构
查询慢,增删快
里面包含了大量操作首尾元素的方法(特有的方法)
注意:在使用LinkedList集合的特有的方法,不能使用多态
1)添加元素
- public void addFirst(E e):插入列表开头
- public void addLast(E e)
- public void push(E e):插入到列表所表示的堆栈;等效于 .addFirst()
2)获取元素
- public E getFirst()
- public E getLast()
注意:如果使用.clear()清空了集合中的元素时,使用上述两个方法,会抛出异常
3)删除元素
- public E removeFirst():删除并返回第一个元素
- public E removeLast()
- public E pop():从列表表示的堆栈中弹出第一个元素;等效于 .removeFirst()
4)判断是否为空
- public boolean isEmpty():不含元素,返回true
73. Vector集合,是单线程,底层用的是数组,是JDK1.0最早期的集合
74. java.util.Set 接口 extends Collection
这里面的方法和Collection接口里面的差不多一致
75. java.util.HashSet集合 implements Set
特点:
1)Set接口有的所有特点
2)是一个无序的集合,存储和取出元素的顺序可能不一样
3)底层是一个哈希表结构(查询的速度非常快)
遍历方式:
- 使用迭代器
- 使用增强for循环
注意:
HashSet存储的自定义类型元素类中,必须重写hashCode和equals方法
76. 哈希值/JDK里的哈希表结构
1)Java里的哈希值,是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个模拟出来的逻辑地址,而不是实际存储的物理地址)
2)在Object类中有一个获取对象哈希值的方法
int hashCode():返回对象的哈希值
hashCode方法的源码:public native int hashCode()
其中,native:代表该方法调用的是本地操作系统的方法
注意:
- 之前对象的地址值(toString)输出的,就是hashCode地址值
- String类重写了Object类的hashCode方法
3)哈希表结构
- JDK1.8版本之前:哈希表 = 数组 + 链表
- JDK1.8版本之后:哈希表 = 数组 + 链表 ;哈希表 = 数组 + 红黑树
两种混合使用。当链表的长度超过了8位时,就会把链表转化为红黑树,来提高查询的速度
77. Set集合存储元素不重复的原理
Set集合在调用add方法的时候,add方法会调用元素的hashCode方法和equals方法,判断元素是否重复
前提:存储的元素必须重写hashCode方法和equals方法
1)先调用hashCode方法计算元素hash值
- 若没有hash冲突,就存入
- 若有hash冲突,就进行 2)
2)调用equals方法比较哈希值相同的元素
78. java.util.LinkedHashSet集合 extends HashSet集合
特点:
- 底层是:哈希表(数组+链表/红黑树)+链表。多了一个链表,用来记录元素的存储顺序,保证元素的有序
79. JDK1.5之后出现的 可变参数
- 前提:当方法的参数列表里的数据类型已经确定,但是参数的个数不确定,就可以使用可变参数
- 使用格式:在定义方法时使用
修饰符 返回数据类型 方法名(数据类型 … 变量名){。。。}
- 可变参数的底层原理
底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数
注意:
- 一个方法的参数列表,只能有一个可变参数
- 如果方法的参数有多个,那么可变参数必须写在参数列表的末尾
可变参数的特殊(终极)写法
public static void method(Object … obj){…}
这种可以接收任意数据类型参数
80. 集合工具类 java.utils.Collections
用来对集合进行一些操作
1)public static < T > boolean addAll(集合,元素,,,):往集合中添加一些元素
2)public static void shuffle(list< ? > list):打乱集合顺序
3)public static < T > void sort(list< T > list):将集合中元素按照默认规则排序
注意:sort使用的前提时被排序的集合里的存储的元素必须:
- 实现Comparable接口
- 并重写接口中的compareTo方法
来定义排序规则
public class Person implents Comparable<Person>{
@Override
public int compareTo(person o){
//升序
//return this - o
//降序
return o - this
}
}
Comparable接口的排序规则:
- 自己(this)- 参数 :升序
- 参数 - 自己(this):降序
4)public static < T > void sort(list< T > list, Comparator< ? super T >):将集合中的元素按照指定规则进行排序
Collections.sort(list,new Comparator<Integer>{
//重写比较规则
@Override
public int compare(Integer o1,Integer o2){
return o1 - o2;//升序
}
});
Comparator的排序规则:
- o1 - o2 :升序
- 可以多写几个规划,组合排序
81. java.util.Map< k, v >集合
Map集合的特点:
1)Map集合是一个双列集合,一个元素包含两个值:一个key,一个value
2)key和value的数据类型可以相同,也可以不同
3)key是不允许重复的,value可以重复
4)key和value时一一对应的
Map接口中的常用方法:
1)public V put(K key,V value):把指定的键和指定的值添加到map集合中
返回值:
- 存储键值对的时候,key不重复,返回值为null
- 存储键值对的时候,key重复,会使用新的value替换map中重复key的value,返回被替换的value值
2)public V remove(Object key)
返回值:
- 返回被删除元素的value值
- key不存在时,返回null
3)public V get(Object key)
返回值:
- key存在时,返回对应的value值
- key不存在时,返回null
4)boolean containsKey(Object key)
判断集合中是否包含指定的键,包含返回true,不包含返回false
82. Map集合遍历的两种方式
- 键找值方式
1)用Set< k > keySet()方法,把Map集合中的所有key取出来存储到Set集合中
2)使用迭代器或增强for循环,遍历Set集合,获取Map集合的每一个key
3)用 .get(key) 方法,获取所有value
- Entry键值对对象方式
Map.Entry< k,v >:在接口Map中有一个内部接口Entry
作用:当Map集合一创建,那么就会在Map集合中创建一个Entry对象,用来记录键与值,即键值对对象/键与值的映射关系
步骤:
1)方法:Set<Map.Entry<k,v>> entrySet():把Map集合内部的多个Entry对象取出来存储的一个Set集合中
2)遍历Set集合,获取Set集合中的每一个Entry对象
3)应用Entry对象中的方法:
getKey():获取key
getValue():获取value
例如:
public static void main(String[] args) {
//创建Map集合对象
Map<String,Integer> map = new HashMap<>();
map.put("赵丽颖",168);
map.put("杨颖",165);
map.put("林志玲",178);
//1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
Set<Map.Entry<String, Integer>> set = map.entrySet();
//2.遍历Set集合,获取每一个Entry对象
//使用迭代器遍历Set集合
Iterator<Map.Entry<String, Integer>> it = set.iterator();
while(it.hasNext()){
Map.Entry<String, Integer> entry = it.next();
//3.使用Entry对象中的方法getKey()和getValue()获取键与值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"="+value);
}
System.out.println("-----------------------");
for(Map.Entry<String,Integer> entry:set){
//3.使用Entry对象中的方法getKey()和getValue()获取键与值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"="+value);
}
}
83. java.util.HashMap< k, v >集合 implements Map< k,v >接口
HashMap的特点:
- HashMap集合底层是hash表,查询速度更快
- 是一个线程不安全的集合,是多线程集合,速度快
- HashMap集合是一个无序的集合,存储元素和取出元素的顺序可能不一致
注意:
HashMap存储自定义类型的键值对时,要保证key值得元素是唯一的,即必须重写hashCode()方法和equals()方法
84. java.util.LinkedHashMap< k,v >集合 extends HashMap< k,v >
特点:
- 底层是哈希表+链表。可以保证迭代的顺序
- 是一个有序的集合,存储元素和取出元素的顺序是一致的
85. java.util.HashTable< k, v >集合 implements Map< k,v >接口
1)HashTable
- 底层是一个哈希表
- 是一个线程安全的集合
- 是单线程集合,速度慢
2)HashMap
- 底层是一个哈希表
- 是一个线程不安全的集合
- 是多线程集合,速度快
1)HashTable
- 不能存储null值和null键
2)之前学过的所有集合
都可以存储null值和null键
HashTable和Vector一样,在JDK1.2之后被更先进的HashMap、ArrayList取代了
但是HashTable的子类Properties仍然在被使用
86. 遍历String字符串,获取每一个字符(两种方法)
1)String类的方法toCharArray,把字符串转化为一个字符数组,在遍历
2)String类的方法length() + CharAt(索引),遍历数组
87. JDK9 在List、Set、Map接口中的新特性:静态方法 of
List、Set、Map接口里面添加了一个静态方法 of,可以给集合一次性添加多个元素
static < E > List< E > of (E …)
使用前提:当集合中的元素个数不再改变的时候使用
注意:
1)of方法只适用于List、Map、Set接口,不适用于接口的实现类
2)of方法的返回值是一个不能改变的集合,集合不能再使用add、put方法添加元素,会抛出异常
3)Set、Map接口在使用of方法时,不能有重复的元素,否则也会抛出异常