admin管理员组文章数量:1531716
day1
Java的优势
- 跨平台 :
- 什么是平台?指的是操作系统
- 操作系统常见的是:Windows Unix Linus Solaris[Sun]
- 什么是跨平台?
- 用java开发出来的应用程序不受底层操作系统的限制 可以运行在所有的操作系统上面
- 底层的功臣:JVM = java虚拟机 = 1 + 2 + 3
- 秘书 = 类加载器 = ClassLoader
- 保镖 = 字节码校验器 = ByteCode Verifier
- 翻译 = 解释执行器 = Interfreter
- 安全 健壮
- 安全性体现在以下三个方面:
- 少指针
- 多异常
- 多自动的垃圾回收 -》 gc
- 安全性体现在以下三个方面:
- 免费 开源
- 简单
- 语法简单:C+±- [取其精华 去其糟粕]
- 糟粕:指针 手动垃圾回收 运算符重载
- 思想简单:面向对象的思想 = OO思想
- 面向过程的思想:需要人站在计算机的角度去思考问题
- 面向对象的思想:需要拿着代码去模拟现实生活
- 类:一组类型相同事物高度抽象之后的集合概念
- 创建对象的模板
- 对象:类的一个具体的实例
- 高启强和人之间的关系:对象和类
- 猫和HelloKitty之间的关系:类和对象
- 猫和动物之间的关系:对象和类
- 引用:对象的名字 java中每一个对象都需要起名字 一个对象同时可以有多个名字 但是如果一个对象一个名字都没有的话 会被gc回收掉 -》 零引用内存回收
- 属性:对象有什么 -》 名词
- 方法:对象会什么 -》 动词
- 类:一组类型相同事物高度抽象之后的集合概念
- 语法简单:C+±- [取其精华 去其糟粕]
- 动态更新:
- 对于核心类库里面提供的一些方法只保留一个指向的关系 当若干年后核心类库升级了 我们的程序还是可以继续使用 这是挤兑c/c++的
day2
- 搭建开发环境
- 第一个程序HelloWorld
- java中的软件包结构
- java中常用的工具命令
搭建开发环境
-
安装jdk
- SDK = software development kits = 软件开发工具包
- JDK = java + SDK = java软件开发工具包
- jdk版本 www.oracle
- 永久修订版 8.0 11.0 17.0
- 非永久修订版
- jdk版本 www.oracle
- JRE = java runtime environment = java运行环境
- JDK和JRE之间的区别?
- JDK叫做java软件开发工具包 一旦电脑安装jdk之后 既可以编写代码又可以运行代码
- JRE叫做java运行环境 一旦电脑安装jre之后 只能运行代码
-
设置环境变量
-
给谁使用 作用
- PATH: 操作系统 让操作系统更加快捷的找到一个文件/命令
- PATH=C:\Program Files\Java\jdk1.8.0_202\bin
- 为什么需要设置环境变量PATH?
- 当我们在E:\课件 -》 Test.java 由于电脑看不懂.java代码 所以ctrl + 1编译成.class文件 ctrl + 1绑定的是javac指定 所以只要按ctrl + 1之后操作系统找javac 操作系统默认去哪里找看PATH指向哪里 PATH默认:C:\Windows\System32
- CLASSPATH: 类加载器 让类加载器明确去哪里加载.class文件
- 一般不需要设置 默认值:.[当前目录]
- JAVA_HOME:一般给其他的人使用的 WEB开发
-
-
设置方式:
- 一次性的设置 cmd设置
- set 环境变量的名字=值
- set PATH=C:\Program Files\Java\jdk1.8.0_202\bin
- set CLASSPATH=.
- set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_202
- set PATH=%JAVA_HOME%\bin
- 环境变量的名字尽量大写
- 当我们给一个环境变量设置多个值的时候 中间用;隔开
- %%:将中间环境变量的值取出来
- 一劳永逸的设置
- 我的电脑 -》 属性 -》 高级 -》 环境变量 -》 编辑 -》 新建
第一个程序HelloWorld
- 我的电脑 -》 属性 -》 高级 -》 环境变量 -》 编辑 -》 新建
- 一次性的设置 cmd设置
-
标识符的命名规范:
- 不能使用数字开头 但是可以用中文 英文 $ _开头
- 不能使用关键字/保留字
-
如何在cmd里面编译运行
- 打开cmd 默认在C盘 假如代码写在E:\课件 -》 Test.java
- 切换盘符 e:回车
- 进入文件夹 cd 将所在的文件夹拖拽进来 回车
- 编译阶段 javac XXX.java
- 运行阶段 java XXX
Java中的软件包结构
- 什么是包结构
- 包等价于操作系统中的文件夹
- 文件夹[包]的作用?
- 按照文件的功能 性质进行分类 方便查找
- 给出不同的命名空间 从而让重名的文件可以同时存在
- 如何打包:
- package : 包 背包
- 必须出现在文件的第一行
- 如何编译运行:
- 编译阶段
- 以前:javac XXX.java
- 现在:javac -d . XXX.java
- 运行阶段
- 以前:java XXX
- 现在:java 包结构.XXX
- 编译阶段
- 在项目开发的时候 尽量避免包名叫:
- com0-com9:打印机设备
- con:网络设备
- nul:空设备
Java中常用的工具命令
- javac 编译指令
- java 运行指令
- javadoc 生成帮助文档
- javadoc -d 说明书 XXX.java
- jar
CLASSPATH=XXXjar
F:java -> Test.java -> Test.class[F:\java] -> ctrl + 2 -> 类加载器加载Test.class
day3
- jar包在项目开发中的应用
- java中的数据类型
- java中的变量
Java中的数据类型
-
什么是数据类型?
- 数据类型其实就是数据的单位 java是一个强类型的编程语言 所有的变量要求在第一次出现的时候必须有数据类型
- 长度:厘米 毫米 千米 米…
- 个数:个 条 只 头栋…
- 钱:角 元 分 百…
-
面试题:java中的数据类型分为几种?
- 2种 无数种
- 基本数据类型 简单数据类型 [程序里面自带的数据类型]
- 面试题:java中的基本数据类型分为几种?
- 4类8种
- 布尔类型:boolean
- 只能使用true[真]/false[假]进行赋值
- 不能使用数字赋值 但是c++可以
- boolean x = true;
- boolean y = false;
- boolean z = 45;//c++可以 java报错
- 字符类型:char 底层基于Unicode编码实现的 无论是中文、英文 统一都是2个字节 = 16个位
- char x1 = ‘a’;//指定字面值的赋值方式
- char x2 = ‘中’;//指定字面值的赋值方式
- char x3 = 97;//通过ascii编码进行赋值
- char x4 = ‘\u4e2d’;//通过Unicode编码进行赋值
- char x5 = ‘\n’;
- 整数类型:符号位 1 + 数值位[n-1]
-
byte short int* long[L]
-
位 8 16 32 64
-
字节 1 2 4 8
-
整数类型默认是int类型
-
当数值超出int类型最大边界的时候 注意使用long类型
-
long类型的结尾需要加上L/l
-
整数类型的赋值方式:
- int x = 45;//十进制
- int y = 045;//八进制
-
-
int z = 0x45;//十六进制
-
int w = 0b1110;//二进制 jdk7.0
-
整数类型和二进制之间的转换:[非重点]
-
取值范围:
-
byte:-128 127
-
short:-32768 32767
-
-
int:-2147483648 2147483647
-
long:-XXXXX XXXXX
- 浮点类型:符号位 + 幂值位 + 数值位
-
float double[*]
-
32 64
-
F/f D/d
-
浮点类型和二进制之间的转换:
- float = 符号位1 + 幂值位8 + 数值位23
- double = 符号位1 + 幂值位11 + 数值位52
-
拓展:BigDecimal[引用数据类型]
- 加法:add()
- 减法:subtract()
- 乘法:multiply()
- 除法:divide()
-
- 浮点类型:符号位 + 幂值位 + 数值位
-
基本数据类型之间的转换:
- 小的数据类型可以直接提升为大的数据类型
- 大的数据类型需要强转成小的数据类型
- byte和char之间需要双向强转
- short和char之间需要双向强转
-
引用数据类型 自定义数据类型 [程序员自己开发的数据类型]
两种数据类型:基本数据类型 简单数据类型 【程序里面自带的】
1、基本数据类型: 四类八种
(1)布尔类型:boolean类型(只能使用true和false赋值)判断句均为boolean
(2)字符类型:char (底层基于Unicode编码实现的,2个字节,单引号’') 【0-65535】
String(内容长度>2) Unicode:cmd->native2ascii
\是转义,\是打印,打印则成对出现
// \t \r \b \n (转义字符)
//制表符 返回行首 退格键 换行
(3) 整数类型:byte(-27~27-1)、 short(-215~215-1)、int(-231~231-1)、long、
位: 8 16 32 64
默认为int,当数值超出int最大边界时,会在范围内循环运算,应转换为long类型,long类型后面加L
0开头为8进制,0x开头为16进制,0b开头为二进制,无0开头为十进制
整数类型(符号位(1正0负)(1位)+数值位(n-1))与二进制的转换:
1+2+4+8+16+32
45=00101101
负数求法:正数二进制取反加一
(4)浮点类型:float(加F/f)、double(加D/d可以加可以不加)(默认)
位: 32 64
浮点型和二进制之间的转换:
符号位+幂值位+数值位
float:1 +8+23 精度最低 double:1+ 11+52
BigDecimal:解决精度损失问题,小数,小数结果不可控不安全 (引用类型)
加法:add() 减法 :subtract() 乘法:multiply() 除法:divide()
(int)强转
byte short int long float double
8 16 32 64 32 64
char (16)
小的数据类型可以直接提升位打的数据类型,大的数据类型需要强转成小的数据类型
byte、short和char之间需要双向强转,int和char是单向强转
所有运算符能处理的最小的单位是int类型
2、引用数据类型 自定义数据类型 【程序员编写开发定义的数据类型】
day4
- java中的运算符
- java中的变量
Java中的运算符
[+ - * / %]
-
+:当+遇到String类型的时候不再表示算数加法 而是表示追加连接
-
*:当心数值超出int类型最大边界 注意使用long类型
-
/:整数除以整数 结果一定是整数
- 求1-100之间最大的8的倍数?
- 100 / 8 * 8 -> 100 >> 3 << 3
- 100 - 100 % 8 -> 100 - (100 & 7)
-
%:取模运算符 求余数 最终结果的符号位取决于参与运算的第一个数的符号
-
+= -= *= /= %=…
- 他们可以保证运算符的左边的数据类型不发生改变 -> 隐式的强转
面试题:
short x = 1;
x = x + 1;//short = int
System.out.println(x);报错
short y = 1;
y += 1;
System.out.println(y);2
- 他们可以保证运算符的左边的数据类型不发生改变 -> 隐式的强转
-
++ --[自增自减运算符]
- [a:取值 b:运算 x++:ab ++x:ba]
-
[> < >= <= ! = != ==]
- [> < >= <=]结果都是boolean类型
- ! : 非 !boolean
- !true = false !false = true
- !=:判断左右两边的值是否不相等
- System.out.println(45 != 66);//true
- =和==之间的区别?
- =:赋值运算符 将右侧的值交给左侧的变量保管
- int x = 45;
- ==:判断左右两边的值是否相等
- System.out.println(45 == 66);//false
- =:赋值运算符 将右侧的值交给左侧的变量保管
-
&& || & |[逻辑运算符]
-
面试题:&&和&之间的区别?
- 相同点:&&和&都是逻辑的与 相当于汉文中并且的意思 需要前后两个条件都成立才能执行
- 不同点:&&叫做逻辑的短路与 有短路特性
- 短路特性:如果通过前面的条件可以得出最终的结果 后面的条件直接舍弃不再判断
- 例子:如果晚上我有空的话 而且你们愿意 那么就考试
- if(我有空 && 你们愿意){考试}
- 18岁女生 -》 age == 18 && gender == ‘女’
-
||和|之间的区别?
-
相同点:||和|都是逻辑的或,相当于汉文中或者的意思,需要前后一个条件成立就能执行
-
不同点:||叫做逻辑的短路或 有短路特性
-
例子:火车站买票 -》出示证件 -》 身份证 || 学生证 || 户口本 || 驾照 ||护照
boolean && boolean
true 判断
false 短路
boolean || boolean
true 短路
false 判断
-
-
-
& | ^ ~[按位运算符] - 基本用法[非重点]
&:按位的与 要求上下二进制都是1才能写1 逢0写0
System.out.println(9 & 5);//1
9:8 + 1 = 000…001001
5:4 + 1 = 000…000101 &
000…000001|:按位的或 要求上下二进制只要有1就写1 逢1写1
System.out.println(9 | 5);//1
9:8 + 1 = 000…001001
5:4 + 1 = 000…000101 |
000…001101 : 8 + 4 + 1 = 13^:按位的异或 要求上下二进制不一样的时候才能写1
System.out.println(9 ^ 5);//1
9:8 + 1 = 000…001001
5:4 + 1 = 000…000101 ^
000…001100 : 12~:按位的取反 0-> 1 1 -> 0
01010010 ~
10101101- 重点 &:在某些情况下可以取代% 某些情况: 当我们想要拿着一个正数 % 上2的n次方数的时候 结果等价于 我们拿着这个正数 & 上2的n次方数-1 的结果 27 %2 %4 %8 %16....2^(n) 1 3 3 11 27 &1 &3 &7 &15....&2^(n)-1 1 3 3 11 System.out.println(100 % 8);100-8-8-8-8-8-8-8 System.out.println(100 & 7);二进制 ^:不采用第三方的形式 交换两个变量的值 int x = 45; int y = 90; int z = x; x = y; y = z; x = x ^ y; y = x ^ y; x = x ^ y;
能够使用^交换的数据类型:
char byte short int long boolean
-
[>> << >>>] 位[二进制位]移运算符
<<相当于乘以 >>相当于除以
移动多少位相当于乘以/除以2的几次方数*2 *4 *8 *16.... *2(n) <<1 <<2 <<3 <<4.... <<n /2 /4 /8 /16...../2(n) >>1 >>2 >>3 >>4.....>>n
和>>>之间的区别?
叫做有符号右移 移动之后空缺的高位看原本的符号位01001011 >> 2 00010010 10001010 >> 3 11110001 >>>叫做无符号右移 移动之后空缺的高位补0 01001011 >>> 2 00010010 10001010 >>> 3 00010001
-
? : [三目运算符 三元运算符]
- boolean ? 2 : 3
- 第一部分为true 那么执行第二部分
- 第一部分为false 那么执行第三部分
一等优先级
[+ - * / %]
[++ --]
[> < >= <= ! = != ==]
[&& || ]
二等优先级:
[+= -= *= /= %=...]
[&取代% <<取代* >>取代/]
[? : 取代 if else]
Java中的变量
-
面试题:java中的变量分为几种?
- 成员变量(实例变量)(属性):定义在类体里面的变量,方法体外面
- 局部变量(自动变量):定义在方法体里面的变量
-
面试题:成员变量和局部变量之间的区别?
(1)定义的位置不同- 成员变量:定义在类体里面的变量
- 局部变量:定义在方法体里面的变量
(2) 作用范围不同 - 成员变量:也叫属性 表示对象有什么 依赖于对象存在 当我们new对象的时候 属性伴随着也会被创建出来 当对象消亡的时候 属性伴随着也会消亡
- 局部变量:从定义的那一行开始 一直到所在的方法体结束之前可以访问 一旦所在的方法体执行结束 局部变量立即消亡 依赖于方法存在
(3) 默认值不同 - 成员变量:即使不赋值也有默认值 默认值看数据类型
-
局部变量:没有默认值 要求使用之前必须先赋值
基本数据类型不能强转为引用类型,可以加new 方法()
引用类型之间必须有继承关系才能转换
区别 成员变量 局部变量
定义的位置不同 定义在类体里面的变量 定义在方法体里面的变量
作用范围不同 依赖于对象存在
当我们new对象的时候,属性伴随着也会被创建出来,当对象消亡的时候,属性伴随着也会消亡 依赖于方法存在
从定义的那一行开始,一直到所在的方法体结束之前可以访问,一旦所在的方法体执行结束,局部变量立即消亡
默认值不同 不赋值也有默认值
默认值看数据类型 没有默认值
要求使用之前必须先赋值
局部变量在使用前必须被初始化
day5
- java中的分支
- java中的循环
- java中的循环控制
Java中的分支
if else
-
语法格式:
if(条件){
执行语句;
}else if(条件){
执行语句;
}else if(条件){
执行语句;
}else{
执行条件;
}
学会使用if else的排他特性简化代码 不要在下面的条件里面写出上面条件不成立的等价判断
*:如果一个方法有返回类型 那么else必须加[否则缺少返回语句] -
拓展内容:
- plus1:当if else里面只有一个语句的时候 {}可以不写
- plus2:当if里面有return语句的时候 else单词不写
- plus3:当if条件为true return true 当if条件为false return false
- 其实return回去的就是条件判断而已
- plus4:不要拿着一个boolean类型的变量和true做连等比较
switch case
-
语法格式:
switch:开关 case : 情况
switch(参数){
case XXX : 语句;[break]
case YYY : 语句;[break]
case ZZZ : 语句;[break]
default : 语句;
}
*:如果一个方法有返回类型 那么里面的break可以不加 default必须加[否则缺少返回语句]
学会使用break共享代码 将执行相同操作的代码放在一起共享面试题:
switch case的参数可以传哪些数据类型?
jdk1.0 char byte short int
jdk5.0 enum[枚举]
jdk7.0 String
Java中的循环
-
for[明确直到循环次数]
- 语法格式:
for(初始化循环变量;循环执行的条件;循环之后的变化){
循环执行的代码;
}
- 语法格式:
-
while[循环条件]
- 语法格式:
1;
while(2){
4;
3;
}
- 语法格式:
-
do while
-
语法格式
1;
do{
4;
3;
}while(2);int x = 1;
do{
System.out.println(x);
x++;
}while(x <= 100);
-
Java中的循环控制
break
continue
- 循环嵌套:一个循环定义在另一个循环里面
- 外层循环一个数字对应整个内层循环
- 循环控制:
- continue[继续]:跳过本次循环剩下的代码 跳到所在循环的第三部分
- break[跳出]:跳出所在循环 跳到所在循环的结束部分
- 循环标签:
- 当多个循环嵌套在一起的时候 如果代码写在最里面 想要处理外层循环 需要给外层循环贴标签 标识符: 然后在内层循环里面continue/break + 标签名
for(int x = 0;x < 10;x++){
for(int y = 0 ;y < 10;y++){
if(){}
}
}
day6
- java中的数组
- 数组复制
- 数组排序
Java中的数组
-
数组:容器 装元素 类型相同 存储空间连续的数据
-
数组的基本用法:
创建数组对象
新数组定义:数据类型[] 数据名 = new 数据类型 [空间大小]-
int[] data = new int[5];//5:空间大小
-
int[] data = new int[]{45,67,11,93,66};
-
int[] data = {11,22,33,44,55,66};
-
如何得到某一个元素:
- data[下标]
-
得到数组长度
- data.length
-
如何遍历数组对象:
- for + 下标
- for(int x = 0;x < data.length;x++){//x:下标 data[x]:元素}
- foreach jdk5.0
- for(数据类型 x : data){//x:元素}
-
数组的复制
-
System.arraycopy(1,2,3,4,5);
- 1:要复制的老数组对象
- 2:老数组的起始下标位置
- 3:要复制到的目标数组
- 4:目标数组的起始下标位置
- 5:要复制的长度
-
Arrays.copyOf(老数组对象,新数组长度);
- import java.util.*;
数组排序
- 冒泡排序 手动排序
for(int x = 0;x < data.length -1;x++){
for(int y = 0;y < data.length -1 - x;y++){
if( 判断语句 ){
数据类型 z = data[y];
data[y] = data[y + 1];
data[y + 1] = z;
}
}
}
for( 数据类型 x : data){
System.out.println(x);
} - 自动排序
- Arrays.sort(数组对象);
- 只能进行升序排序
- import java.util.*;
day7
-
引用数据类型的数组
-
面向对象的三大特点
-
方法重载
-
方法覆盖
-
当我们创建一个引用数据类型的数组的时候 其实里面一个元素都没有 里面装的都是默认值null 为了防止出现空指针异常 那么给每块空间赋值
面向对象:
- 三大特点:封装 继承 多态
- 四大特点:封装 继承 多态 抽象
封装
用private将不想被外界访问到的属性/方法隐藏起来
- private : 私有的 只有本类可以访问
- public : 公共的 谁都可以使用的
- 封装的好处?
- 类的开发者:数据得到了保护 从而更加的安全
- 类的使用者:将精力放在核心业务逻辑上
- 如何封装:
- 对属性的封装:
- 所有的属性前面都加上private 每个属性提供两个public修饰的方法
- 一个是用来给属性赋值的方法 -》 setter[设置]
- public void setXXX(参数){this.属性 = 参数;}
- 一个是用来得到属性值的方法 -》 getter[获得]
- public 返回类型 getXXX(){return 属性值;}
- 对方法的封装:
- 判断哪些是核心方法 核心方法用public修饰
- 给核心方法提供服务的方法 -》 private修饰
- 对属性的封装:
继承
用extends[派生]实现两个类[子类 extends 父类]之间is a[是一个 是一种]的关系
- 继承是最简单的代码共享方式之一
- java中的类只能单根继承
多态
一个对象有不同的类型去定义它
- 创建对象:父类类型 = new 子类对象(); [了解]
- Animal aa = new Cat();
- Person x = new Student{}
- 当我们拿着多态创建完一个对象之后 这个对象只能调用父类和子类共有的属性/方法 一旦调用子类特有的属性/方法 报错
- 编译阶段 编译器只看等号的左边进行语法检查
- 放在参数里面用于解除代码之间的耦合度
- 耦合度:代码之间的相互依赖程度
- 高内聚 低耦合
方法重载 Overload
方法过载
- 面试题:
- 方法重载需要哪些条件?
(1) 需要发生在同一个类体中
(2)方法名需要一模一样
(3) 方法的参数需要不同
- 参数类型不同
- 参数个数不同
- 参数的顺序不同
- 方法重载对修饰符和返回类型没有要求
- public static void test(){}
- public int test(int x){}
- 方法重载有哪些作用?
- 同时满足用户的不同需求
System.out.println() println()
System.out.println(45) println(int)
System.out.println(4500L) println(long)
System.out.println(4.5) println(double)
System.out.println(“etoak”) println(String)
System.out.println(true) println(boolean)
System.out.println(‘a’) println(char)
System.out.println(stu) println(Object)
方法覆盖 Override
方法重写
面试题:方法覆盖需要哪些条件?
- 需要发生在有继承关系的两个类中 子类继承得到父类的某些方法觉得父类的实现不好 于是在子类里面重新实现一下
方法覆盖需要注意:
public void test()throws Exception{}
| |
脑袋 躯干 尾巴
脑袋:访问权限修饰符 >= 父类的权限
Sun公司认为子类重新实现的方法应该更加优秀 更加优秀的方法
应该给更多的人使用 这样才利于java的发展
躯干:返回类型 + 方法签名
jdk5.0之前 一模一样
jdk5.0开始 协变返回类型
尾巴:异常处理部分 <= 父类的异常 [范围]
Sun公司认为子类重新实现的方法应该更加优秀 更加优秀的方法
不应该有更多的隐患
-
jdk5.0开始 方法覆盖的时候可以加@Override 表示下面的方法一定要覆盖父类的某些方法
-
jdk5.0开始 方法覆盖的时候 其实返回类型可以改变了
- 可以变成父类方法返回类型的子类类型 -》 协变返回类型
-
面试题:Override和Overload之间的区别?
含义不同 方法重载Overload 方法覆盖Override
发生的位置不同 发生在同一类体中 发生在两个具有继承关系的子类中
对参数的要求不同 参数必须不同
(类型、个数、顺序) 参数必须相同
对返回类型的要求不同 无要求 jdk5.0前一模一样之后协变返回类型
作用不同 同时满足用户的不同需求 让一个方法变得更优秀
day8
- 构造方法
- 扫描仪
- 方法封装的好处
构造方法
-
构造方法是创建对象的方法
-
构造方法是创建对象的时候调用的方法 -》 收尾的工作
-
构造方法的作用?
- 构造方法语法的出现是为了方便程序员的开发 可以再创建对象的同时直接给属性赋值
- 任何一个类都有构造方法 即使我们没有写 系统也会提供一个默认的构造方法 默认的构造方法是无参空体
- 如果想要在创建对象的时候给所有属性赋值的话 需要自己写一个构造方法 一旦我们写出自己的构造方法之后 默认的无参构造方法将不再提供 HGDSHGDGJF
-
构造方法的特点:
- 没有返回类型 连void都不能写 -》 修饰符 + 方法签名(){}
- 构造方法的名字需要和类名一模一样的[通常首字母大写]
-
构造方法的首行…
- 默认:super():要执行本构造方法之前 先去执行父类的构造方法 默认找父类无参构造方法
- 如果父类没有无参构造方法
- 提供父类的无参构造方法
- 在super()里面传参数 指定他找父类的哪一个构造方法
- 如果父类没有无参构造方法
- 构造方法的首行还可以出现this()
- this():要执行本构造方法之前 先去执行本类的其他的构造方法 具体执行本类的哪一个构造方法 看参数类型
- 默认:super():要执行本构造方法之前 先去执行父类的构造方法 默认找父类无参构造方法
-
构造方法首行的super()/this()只能出现一个
super.和this.之间的区别?- super.和this.一般出现在普通方法里面 没有位置限制
- super.在子类调用父类的某个普通属性/普通方法
- this.当前调用该方法的对象
-
super()和this()之间的区别?
- super()/this()只能出现在构造方法的首行
- super():表示要执行本构造方法之前 先去执行父类的构造方法 具体执行父类的哪一个构造方法 看参数类型
- this():表示要执行本构造方法之前 先去执行本类的其他的构造方法 具体执行本类的哪一个构造方法 看参数类型
- super()/this()只能出现在构造方法的首行
-
构造方法能不能方法重载?
- 可以重载
-
构造方法可以方法覆盖吗?
- 不可以 因为构造方法不能被子类继承
+++
- 不可以 因为构造方法不能被子类继承
扫描仪:Scanner 需导包:import java.util.*;
Scanner sc =new Scanner(System.in);
Day9
- 参数传递
参数传递:
- java中只有值传递
- java中的基本数据类型传值 引用数据类型传地址
day10
- String类常见的面试题
- String类常用的20个方法
String类常见的面试题
- new和不new之间的区别?
- String x = “OK”;
- String y = new String(“OK”);
- 不new的方式直接去常量池查看 如果有该单词 直接从常量池里面取出来使用 如果没有的话 在常量池里面缓存一份
- new的方式先在堆里面开辟,与此同时还会去常量池里面查看
- String str = new String(“易途”);这一行代码内存里面创建了几个对象?
- 2个对象 -》 堆对象 + 常量池
- String和StringBuffer/StringBuilder之间的区别?
String没有缓存区,而StringBuffer/StringBuilder有缓存区- String str = new String(“OK”);
- StringBuffer buffer = new StringBuffer(“OK”);
- StringBuffer和StringBuilder在第一次创建对象的时候 底层会多预留16块缓冲区 为了追加连接效率高
- String在创建对象的时候 空间大小永远是刚刚合适
- StringBuffer和StrtingBuilder之间的区别?
- StringBuffer同一时间允许一个线程进行访问 效率较低 但是不会出现并发错误
- StringBuilder同一时间允许多个线程进行访问 效率较高 但是可能会出现并发错误
面试题:
区别(不同) String StringBuffer
有没有缓冲区的问题 没有缓冲区,单词多长内存空间多大 有缓冲区,在第一次创建对象的时候底层会多预留16块缓冲区
创建对象的方式不同 new和不new,两种 必须new,一种
能不能直接修改原本的字符串 不可修改
不可改变类型 所有的方法都不会直接的处理原本的字符串 可修改
可以改变类型 所有的方法都直接处理原本的字符串
Equals不同 比较内容 比较地址
StringBuffer buffer = new StringBuffer(); 必须要new一下
append() 字符串 追加连接,相当于+号 //只能用于StringBuffer
reverse() 无参 反转字符串,倒过来
buffer.append(p.getClass().getName());//(固定的)得到类名
String类常见的20个方法
和长度有关的方法
***data.length-》数组长度
返回类型 方法签名 作用
int length() 得到一个字符串里面的字符个数
和数组有关的方法
返回类型 方法签名 作用
byte[] getBytes() 将一个字符串转换成字节数组
char[] toCharArray() 将一个字符串转换成字符数组
String[] split(String) 将一个字符串按照指定的内容劈开
和判断有关的方法
返回类型 方法签名 作用
boolean equals(String) 比较两个字符串的内容是否一样
boolean equalsIgnoreCase(String) 忽略大小写的比较两个字符串的内容是否一样
boolean contains(String) 判断一个字符串里面是否出现某个内容
boolean startsWith(String) 判断一个字符串是否以指定的内容开头
boolean endsWith(String) 判断一个字符串是否以指定的内容结尾
和改变内容有关的方法
String类是不可改变类型,所有的方法都不会直接的处理原本的字符串,而是将符合条件的字符串返回给我们,所以注意接收.
返回类型 方法签名 作用
String toUpperCase() 将一个字符串全部转换成大写
String toLowerCase() 将一个字符串全部转换成小写
String replace(String,String) 将字符串里面的某个内容全部替换成指定的内容
String replaceAll(String,String) 将字符串里面的某个内容全部替换成指定的内容【支持正则表达式】
String replaceFirst(String,String) 将字符串里面第一次出现的某个内容替换成指定的内容
String trim() 去除字符串的前后空格
String substring(int x,int y) 从下标x一直截取到下标y-1对应的元素
String substring(int x) 从下标x一直截取到字符串的最后
和位置有关的方法
返回类型 方法签名 作用
char charAt(int) 找到指定下标对应的元素
int indexOf(String) 找到一个内容第一次出现的下标
int lastIndexOf(String) 找到一个内容最后一次出现的下标
`
和匹配有关的方法
返回类型 方法签名 作用
Boolean matches(String) 判断左边的字符串是否符合右边的正则表达式
StringBuffer方法
append(String):追加连接
reverse(String): 反转
==:判断左右两边的值是否相等
//基本数据类型:比较数值
//引用数据类型:比较地址
String[] data = str.split(“,”); //劈开
System.out.println(data.length);
for(String x: data){ //包含
if(x.contains(“一”)){
System.out.println(x);
} }
for(String name : data){ //长度
if(name.length() >= 4){
System.out.println(name);
} }
int count = 0;
for(String x : data){
if(x.startsWith(“陈”)){
count++;
} }
System.out.println(count);
String str1 = “etoak”;
//将替换成
str1 = str1.replace(“”,“”);
System.out.println(str1);
String str2 = “73trqw7yq”;
//将字母和数字分离
String a = str2.replaceAll(“[a-z]”,“”);
String b = str2.replaceAll(“[0-9]”,“”);
//删除汉字
String c=str2.replaceAll(“[\u4e00-\u9fa5]”,“”);
System.out.println(a + " " + b + " ");
//普通属性:依赖于对象存在 对象.x
//静态属性:不依赖于对象存在 对象.y 类.y
//普通方法:依赖于对象存在 对象.test()
//静态方法 不依赖于对象存在 对象.show() lei.show()
//this:当前调用该方法的对象,不能出现在静态方法里面
static://静态属性:依赖于类存在 //局部变量:依赖于方法存在
day11
- StringBuffer类核心方法
- 面向的高阶特征:
面向对象的高阶特征
- 访问权限修饰符:
- public : 公共的 表示谁都可以使用的 - private : 私有的 只有本类可以访问的
- protected : 受保护的 只有本包内可以访问 + 包外有继承关系的子类中可以访问
- default : 默认的 只有本包[package]内可以使用
- 他们各自能修饰哪些东西
public protected default private
定义 公有的 受保护的 默认的 私有的
修饰类 T F T F
修饰成员[属性、方法] T T T T - 面试题:A类里面定义一个public修饰的方法 在B类里能使用吗?
- 不一定,如果B类想要访问A类里面公共的方法 前提是需要先能访问到A类
Static修饰符
修饰符 表示静态的 相当于汉文中的形容词
- static可以修饰什么?
- 属性:静态属性 表示整个类型共享一份的属性 需要拿着类名去调用
- 普通属性:表示每个对象都有一份的属性 需要拿着对象去调用
- 方法:静态方法 需要拿着类名去调用
- 普通方法:需要拿着对象去调用
- 开发的时候之所以没有把所有的方法都写成静态的原因?
- 静态的方法里面只能直接的访问静态的成员 如果想要访问非静态的成员 需要创建对象 拿着对象去调用
- 普通方法里面既可以访问静态成员也可以访问非静态的成员
- 代码块:初始化一个普通属性
- 当我们想要初始化一个静态属性的话 -》 static{}
- 普通代码块用来普通属性赋值的,当创建对象的时候执行,创建几个对象执行几次
- 静态代码块用来静态属性赋值的,当类第一次被加载的时候执行,从头到尾执行一次
- 面试题:java中变量大还是属性大?
- 变量大
- static为什么不能修饰局部变量?
- static修饰的变量要求类一加载就要在内存里面找到他 但是局部变量只有方法调用 代码执行到这一行的时候才能创建 类的加载永远在前面 方法调用永远在后面 这两个时间点赶不上一起的 所以static不能修饰局部变量
- 属性:静态属性 表示整个类型共享一份的属性 需要拿着类名去调用
单例模式
控制一个类有且只有一个对象 (共23种模式)
- 醉汉式 饿汉式 步骤:
- 私有化构造方法,防止外界随意的创建对象
- 创建一个私有的 静态的 属于本类类型的对象
- 提供一个公共的 静态的 返回本类对象的方法
class Sun{ 醉汉式
Private Sun(){} //private:私有化构造方法 防止外界随意的创建对象
Private static Sun only = new Sun() ; //static:防止死循环 private:防止外界随意改动
Public static Sun getOnly(){return only} //public:封装的要求 static:防止方法依赖于对象存在
} 主方法里接一下: Sun x=Sun.getOnly(); 再打印输出
//getClass().getName() 根据传的数据来获取它的类名
懒汉式: 尚不完善
class Sun{
private Sun(){}
private static Sun only ;
public static Sun getOnly(){ //public static synchronized Sun getOnly(){ 上个锁
If(only ==null){
Only = new sun();
return only;
} }
Final修饰符
修饰符 表示最终的 相当于汉文中的形容词
-
final能修饰哪些东西?
-
类:最终类 “骡子类”
- 不能有子类 但是可以有父类
- String和Math类型都是最终类
-
方法:最终方法
- 可以被子类继承 但是不能被覆盖(@override)
-
变量:[属性 + 局部变量]:最终变量 常量
-
一旦赋值之后就不能在修改值
-
final 基本数据类型 -》 数值不变
-
final 引用数据类型 -》 地址不变
-
abstract修饰符
抽象的 修饰符 相当于汉文中的形容词
-
abstract能修饰哪些东西?
-
类:抽象类 表示这个类型不形象不具体 不能创建对象
- 抽象类是类吗?是
- 抽象类有构造方法吗?有 Java中只要是个类就有构造方法
- 抽象类特有构造方法但是不能创建对象 那么抽象类里面的构造方法作用?
- 给子类构造方法首行的super()使用的
-
方法:抽象方法 表示这个类型一定会这个方法 但是现在给不出具体的实现 待留给子类去实现,即方法覆盖
- 一个类里面只要有抽象方法 那么这个类一定要变成抽象类
- 抽象类里面既可以定义抽象方法 又可以定义普通方法
-
面试题:final和abstract能不能同时修饰一个方法?
- 不能
- final修饰的方法叫做最终方法 不能被覆盖
- abstract修饰的方法叫抽象方法 需要子类去覆盖
二者矛盾
day12
- 接口:
- Object类:
接口interface
相当于工业生产中的规范
-
第二大类型:[他们都可以再编译之后生成.class文件]
- class interface enum @interface
- 类 接口 枚举 注解
-
如何定义接口
interface XXX{
接口里面的属性默认加上三个修饰符:public static final
String str = “etoak”;
int v = 45;
接口里面的方法默认加上两个修饰符:public abstract
void test();
int show();
} -
两两之间的关系:
- 类和类:extends
- 类和接口:implements
- 接口和接口:extends
- 一个类只能继承一个类型
- 一个类可以实现多个接口
-
接口不能创建对象 因为她也是抽象的
-
接口和抽象类之间的区别?
- 这是java中的两大类型:
- 抽象类:class
- 接口:interface
- 里面的属性不同
- 抽象类:默认都是普通属性 default
- 接口:默认都是静态的最终变量:public static final
- 里面定义的方法
- 抽象类:既可以定义抽象方法 也可以定义普通方法
- 接口:只能写抽象方法 -》 public abstract
- jdk8.0开始 接口里面可以出现普通方法:必须加上static/default
- jdk9.0开始 接口里面可以出现私有方法了
- 这是java中的两大类型:
-
继承关系不同
-抽象类只能单根继承
-接口类多继承,多实现
Object类:
- clone():"克隆"对象的方法
- toString():
- equals():
- hashCode():
day13
- 深克隆和浅克隆
- toString()
- equals()
- hashCode()
- Java中的集合
深克隆和浅克隆
Object类核心方法
clone()
:"克隆"对象的方法
toString()
制定一个对象打印显示的内容
- 任何一个类都继承自Object 都可以获得toString()
- toString()在没有覆盖的时候和Object类型保持一致
- 在Object类中 toString():打印对象 -》 类型@XXX
- 如果不满意需要覆盖:(在自定义的类中对toString方法进行覆盖)
public String toString(){//这一行不能改
… //return name+age+gender;
} - 数组类自己的toString()没有覆盖 但是Sun公司提供一个方法:Arrays.toString(数组对象):可以快速方便的打印数组里面的内容
equals()
制定一个类型的比较规则
-
任何一个引用数据类型都继承Object 得到equals()
-
如果没有覆盖equals()在Object类型里面比较两个对象的地址
-
如果不想要比较地址的话那么需要覆盖equals()
public boolean equals(Object obj){
if(obj == null)return false;//保障健壮性
if(!(obj instanceof 当前类型))return false; //保障健壮性
if(obj == this)return true; //保障效率
return this.name.equals(((类型)obj).name) && this.age == ((类型)obj).age;
}
写法:对象 instanceof 类 instanceof :判断左边的对象是否属于右边的类型
//由于参数是Object类型,所有引用数据类型的默认值都是null 为了防止出现空指针异常 所以只要参数是null 那么直接返回false,为了保证代码的健壮性
//由于参数是Object类型,所以所有的引用数据类型都传递进来,但是学生类的equals()应该和学生作比较,所以只要参数不是当前类型,直接返回false,保证代码的健壮性
// if(obj == this)return true;保证代码的高效性
继承得到 Object String(没有覆盖之前sun公司定义) Student(自己定义)
toString() 打印对象 String@XXX Student@XXX
Equals() 比较对象 比较地址 比较地址
hashCode() 生成哈希码值 通过地址 通过地址 -
面试题:==和equals()之间的区别?
==是一个运算符,判断左右两边的值是否相等
==比较基本数据类型:比较数值是否一样
equals引用数据类型:比较地址是否一样
- equals()是Object类型里面一个方法 程序员可以按照自己的意愿将内存里面不同的两个对象视为相等对象 比如:String类通过覆盖equals()将两个不同的对象只要内容一样就视为相等对象
hashCode()
:得到一个对象的散列特征码
- 散列:将一大组数据分散为不同的小组
- 注意:当此方法(equals)被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
Java中的集合
集合:容器 用来装元素 可以装不同类型的元素 没有个数限制
数组:容器 用来装元素 只能装同类型的元素 有个数限制
JCF:Java Collections FrameWork java集合框架
Collection【单值类型的集合】:每次往集合添加一个元素 Map[键值对类型的集合]:每次往集合里面添加一对键值对[key = value]
List(collection接口的子类) Set 子类 (SortedSet) SortedMap
[有序] [不唯一] [无序] [唯一] [有序] [唯一]
案例1:拿着一个集合装每一桌客人点的菜品 按照凉菜 热菜 汤 主食的顺序上菜 -》 List
案例2:拿着一个集合装班级学生的信息,按照分数降序 -》 sortedSet
案例3:图书馆管理系统,存储哪一个学生借了哪一本书 -》Map
案例4:大润发超市系统底层需要存储每个会员的信息 -》 Set
-
什么是单值类型的集合?
- 每次往集合里面添加一个元素
- word文档 -》 集合装大量的常见的英语单词
- 集合 -》 apple animal cat orange…
-
什么是键值对类型的集合?
- 每次往集合里面添加一对元素 -》 key[主键]=value[值]
- 金山词霸 -》 apple = 苹果
- 集合 -》 apple=苹果 animal=动物
-
List接口
-
实现类:
-
ArrayList
-
-
特点:有序 不唯一
-
数据结构:数组
-
ArrayList0:包装类
-
-
由于ArrayList底层基于Object[]实现的,所以所有的引用数据类型都可以存储在集合里面,但是基本数据类型不可以,为了保证基本数据类型也可以存储在集合里面,所以引出包装类
引用数据类型 -》 集合
基本数据类型 -》 包装类 -》 集合
- int x = 45;
- Integer y = x;//自动打包 封箱
- Integer a = new Integer(88);//标记过时
- int b = a;//自动解包 拆箱
Integer会自动的缓存:-128到127
-
包装类里面提供一个方法可以将字符串转换成对应的基本数据类型
- String str = "123";
-
int num = Integer.parseInt(str);
-
Vector : 语法和ArrayList一模一样,基于数组存在
- LinkedList : 底层数据结构不同,基于链表存在
- Stack:用数组模拟栈结构 push()添加 pop()拿,取值
matches() 方法用于检测字符串是否匹配给定的正则表达式
字符串对象.matches(“正则”):判断左边的字符串是否符合右边的正则表达式
day14
ArrayList集合
-
ArrayList0:包装类:
- 由于ArtrayList底层基于Object[]实现 所以只能装引用数据类型 为了将基本数据类型也可以存储在集合里面,引出包装类的概念
- int x = 45;
- Integer y = Integer.valueOf(x);//5.0之前
- Integer y = x;//5.0开始 自动打包
- 包装类里面提供一个方法 可以字符串转换成基本数据类型
- String str = “123”; - int num = Integer.parseInt(str);
- 由于ArtrayList底层基于Object[]实现 所以只能装引用数据类型 为了将基本数据类型也可以存储在集合里面,引出包装类的概念
-
ArrayList1:基本用法及特点:
(1)创建对象:ArrayList<泛型> list = new ArrayList<>();//后面泛型可以不写
(2)添加元素:list.add(元素);一次向尾部添加一个元素
list.add(下标,元素);往某个位置插入一个元素,其余元素后移
Collections.addAll(集合,元素,元素…);一次添加多个元素 ,如何实现的呢?addAll()基于可变参实现,可变参底层基于数组实现,一个方法只能存在一个可变参,可变参只能在参数的最后【 可变参类型 … 变量名 】
Collection和Collections之间的区别?
Collection是所有单值集合统一的父接口:interface Collections是集合工具类:class(3)修改某个下标对应的元素: list.set(下标,元素);
(4)得到某个元素: list.get(下标);得到某个元素第一次/最后一次出现的出现的下标 int x = list.indexOf(元素); int y = list.lastIndexOf(元素);
(5)判断集合是否包含/存在某个元素: boolean x = list.contains(元素);
判断集合是否为空: boolean x = list.isEmpty()
集合清空list. clear()
集合大小int size = list.size()(6)将集合转换成数组:Object[] data = list.toArray();
T[] = list.toArray(new T[空间大小]); T:代表引用类型的数组,不能写基本数据类型
(7)集合遍历:
① for + 下标
for(int x = 0;x < list.size();x++){
System.out.println(list.get(x));
}
②foreach
for(Integer x : list){
System.out.println(x);
}
③迭代器:用于带有循环的集合里面的删除!hasNext():判断迭代器上面是否还有一个元素-》boolean类型
next:取出下一个元素 remove :删除当前的元素
for(Iterator<Objcet的类型> car = list.iterator();car.hasNext(){
Objcet的类型ff= car.next();
if(ff.name.contains(“西红柿”)){
car.remove();
}
}
(8)删除元素: list.remove(下标):指定下标删除 list.remove(元素):指定元素删除,如果删除重复的某个,需要循环删除 ,一个remove()只能删除一个元素(因为源码的remove只有一个return)
底层遵循equals():
ArrayList底层的:
remove(obj元素)day13->TestArrayList5
contains(obj元素) day13->Exec4
indexOf(obj元素) day13->TestArrayList5Plus
lastIndexOf(obj元素)
底层需要调用equals()作比较
add(元素) 将新来的元素装进列表末尾,不唯一
remove(下标) 利用数组复制实现 将后面的元素往前移动
remove(元素) 拿着被删除的元素和集合元素做equals(),一个remove()只能删除一个对象,equals()方法中只存在一个return,所以我们只能删除一次删除一个对象
contains(元素) 拿着被包含的元素和集合元素做equals()
indexOf(元素) 拿着被查找的元素和集合中的元素做equals()
(9)list.clear():清空集合
list.remove(元素)能不能删除成功取决于equals()
list.contains(元素)能不能返回true取决于equals()
//IndexOutOfBoundsException:集合下标越界
//ArrayIndexOutOfBoundsException:数组下标越界
//StringIndexOutOfBoundsException:字符串下标越界
谁主张谁举证,要被删除的对象会主动调用它自己类的equals()和集合里面的每个元素作比较
-
ArrayList5:当我们使用迭代器在遍历集合的时候 不允许对集合的整体进行添加/删除 否则触发ConcurrentModificationException=CME(并发修改异常)异常 如果需求决定一定要一边遍历 一边删除的话:迭代器的删除: - car.remove();
-
ArrayList6:构造方法:
- ArrayList list = new ArrayList(3000000);// int 容量数组空间大小
- ArrayList list = new ArrayList();//默认10块
- ArrayList list = new ArrayList(单值集合);//将该集合元素装进list集合里面
- 扩容:list.ensureCapacity(1000000)//int 容量
- 缩容:list.trimToSize();//无参方法
ArrayList7:可变参
//可变参底层基于数组的实现
//注意:
//一个方法里面只能出现一个可变参
//可变参只能放在参数的最后
//不要在本类里面出现一个等价的数组类型的参数
public static void test(int … x){//x:数组
for(int y : x){
System.out.println(y);
}
}
ArrayList8:包装类
包装类:由于ArrayList底层基于Object[]实现的 所以可以装所有引用数据类型 但是不能装基本数据类型,为了保证集合里面也可以装基本数据类型 -》 包装类
引用数据类型 -》 集合
基本数据类型 -》 包装类 -》 集合
boolean char byte short int long float double
Boolean Character Byte Short Integer Long Float Double
JCF:java集合框架
Collection[单值类型的集合] Map[键值对类型的集合]
List Set SortedMap
[有序] [无序]
[不唯一] [唯一]
ArrayList、LinkedList、Vector SortedSet hashSet
Stack [有序]
[唯一]
day15
- ArrayList复习
- LinkedList
- Vector
- Stack
ArrayList、LinkedList、Vector、Stack区别
- 创建ArrayList对象:
- ArrayList<泛型> list = new ArrayList<>();//默认10块空间
- ArrayList<泛型> list = new ArrayList<>(int 数组容量);
- ArrayList<泛型> list = new ArrayList<>(单值集合);
- 如何添加元素: - list.add(元素); - Collections.addAll(集合,元素,元素…);
- 修改某个元素: - list.set(下标,元素)
- 得到某个元素: - list.get(下标)
- 判断集合里面是否存在某个元素: - list.contains(元素) - contains底层尊重equals()原理
- 如何得到集合大小 - list.size()
- 如何删除元素 - list.remove(int 下标); - list.remove(Object 元素):底层尊重equals()
- 批量删除 -》 遍历删除 -》 迭代器 -》 car.remove()
- 扩容:list.ensureCapacity(数组空间)
- 缩容:list.tirmToSize()
Vector:语法和ArrayList一摸一样的
- 面试题:ArrayList和Vector之间的区别?
- 同步特性不同
- Vector同一时间允许一个线程进行访问 效率较低 但是不会出现并发错误
- ArrayList同一时间允许多个线程进行访问 效率较高 但是可能会出现并发错误
- jdk5.0开始 集合的工具类里面提供一个方法可以将线程不安全的ArrayList变成线程安全的List集合 于是Vector渐渐被淘汰了
- List list = Collections.synchronizedList(ArrayList对象);
- 扩容机制不同
- Vector分构造方法
- Vector(8) -> 2倍扩容 8 -》 16 -》 32-》 64…
- Vector(10,3) -> 定长扩容 10 -》 13 -》 16 -》 19…
- ArrayList分版本
- jdk6.0及之前 x * 3 / 2 + 1
- jdk7.0及之后 x + (x >> 1)
- Vector分构造方法
- 出现的版本不同
- Vector since jdk1.0
- 同步特性不同
- ArrayList since jdk1.2
LinkedList:语法和ArrayList一摸一样的
- ArrayList和LinkedList之间的区别?
区别:底层数据结构不同 导致他们的优劣势不同
ArrayList 底层基于
数组实现的 优点 查找、随机访问效率高O(1)
缺点 增加、删除、插入效率低O(n)
LinkedList 底层基于
链表实现的 优点 增加、删除、插入效率高O(1)
缺点 查找随机访问效率低,永远从下标0开始找O(n)
- 当我们使用LinkedList的时候 尽量避免使用get(下标)
Stack:用数组模拟栈结构
day15
- HashSet集合
ArrayList HashSet
有序(默认添加顺序有序),不唯一 无序(无下标),唯一,哈希表实现
创建对象 ArrayList<泛型> list = new ArrayLIst<>(); HashSet<泛型> set = new HashSet<>();
添加元素 List.add(元素); Set.add(元素);
List.Collections.addAll(集合名,元素,…); Set.Collections.addAll(集合名,元素,…);
是否存在某个元素 List.contains(元素); Set.contains(元素);
得到集合大小 List.size(); Set.size();
判断集合是否为空 Boolean x = List.isEmpty(); Boolean x =Set.isEmpty();
删除元素 list.remove(下标);int 无(set集合都没有下标)
list.remove(元素);Object底层尊重equals() - 批量删除 -》 遍历删除 -》 迭代器 -》 car.remove() set.remove(元素);Object
底层拿着hashCode() == equals()比较
当我们使用迭代器在遍历集合的时候,不允许对集合的整体进行添加/删除,否则触发ConcurrentModificationException=CME异常,如果需求决定一定要一边遍历一边删除的话:迭代器的删除: - car.remove();
for(Iterator<泛型> car = list.iterator;
car.hasNext(){
泛型 x = car.nex();
if(f.name.contains(“”)){
car.remove();
}
}
for(Iterator<泛型> car = set.iterator;
car.hasNext(){
泛型 x = car.next();
if(f.name.contains(“”)){
car.remove();
}
}删除 + 修改 + 添加
//hasNext():判断迭代器上面是否还有一个元素-》boolean
next:取出下一个元素
remove :删除当前的元素
遍历元素
for+下标
foreach
迭代器 3种方法 2种方法
for(int x=0;x<list.size();x++){
System.out.println(list.get(x));
} 无
for(类型 x : list){
System.out.println(x);
} for(类型 x : set){
System.out.println(x);
}
for(Iterator<泛型> car = list.iterator;
car.hasNext(){} for(Iterator<泛型> car = set.iterator;
car.hasNext(){}
Set集合:接口 set集合都没有下标
HashSet集合
-
特点:无序(打印的顺序是无序的) 唯一(同一个元素只能出现一次) - 数据结构:哈希表实现的
-
HashSet1:基本用法及特点
-
创建对象: HashSet<泛型> set = new HashSet<>();
-
添加元素: -set.add(元素); - Collections.addAll(集合,元素,元素…);
-
得到集合大小: - set.size()
-
判断集合里面是否存在某个元素: - set.contains(元素)
-
删除元素: - set.remove(元素)
-
遍历集合: - foreach + 迭代器
-
HashSet2:
- 即使不是内存里面的同一个对象也有可能被视为相等对象 从而只能添加一个元素进集合里面
-
HashSet3:day15-> TestHashSet3
- HashSet在添加元素的时候 其实完整比较流程(3个):
-
hashCode() == equals()
ArrayList -> add(元素) -》 不需要做任何作比较 直接添加
HashSet -> add(元素) -》 需要做hashCode() + equals()比较 -
HashSet4:
- HashSet集合在遇到重复元素的时候 舍弃是新来元素
- HashSet集合底层的add(元素) remove(元素) contains(元素)
底层尊重hashCode() == equals()比较机制
-
HashSet5:
- 当我们使用迭代器在遍历集合的时候 不允许对集合的整体进行添加/删除操作 否则触发CME异常
- 如果在遍历的时候想要删除的话 car.remove()
-
HashSet6: day15-> TestHashSet7
-
当一个对象已经被装进HashSet集合之后 不要随意的修改那些参与生成哈希码值的属性值 如果在添加之后想要修改的话:
删除 + 修改 + 添加
-
HashSet7
HashSet底层的:
***add(元素) day15-> TestHashSet3
remove(元素) day15-> TestHashSet5
contains(元素) day15-> TestHashSet5
底层尊重hashCode() == equals()
创建对象:
- ArrayList<> list = new ArrayList<>();//默认10块空间
- ArrayList<> list = new ArrayList<>(int 数组大小);
- ArrayList<> list = new ArrayList<>(单值集合);
- HashSet<> set = new HashSet<>();//默认16个小组 加载因子0.75F
- HashSet<> set = new HashSet<>(单值集合);
- HashSet<> set = new HashSet<>(int 分组组数,float 加载因子);
- HashSet<> set = new HashSet<>(int 分组组数);//默认加载0.75F
添加元素:
- list.add(元素)//底层不需要作比较 因为List集合不唯一
- Collections.addAll(集合,元素,元素…);
- set.add(元素);//底层找hashCode() == equals()
- Collections.addAll(set,元素,元素,元素…);//hashCode() == equals()
修改某个下标对象的元素:
- list.set(下标,元素)
得到某个下标对象的元素 - list.get(下标)
Set没有下标
得到集合大小
- list.size()
- set.size()
判断集合是否为空
- list.isEmpty()
- set.isEmpty()
判断集合里面是否包含某个元素
- list.contains(元素) -》 底层拿着equals()作比较
- set.contains(元素) -》 底层拿着hashCode() == equals()做比较
如何删除集合的元素:
- list.remove(int 下标)
- list.remove(Object 元素) -》底层拿着equals()比较
- set.remove(Object 元素) -》 底层拿着hashCode() == equals()比较
如果想要在遍历的时候进行删除的话:
-
迭代器删除
JCFCollection Map [单值集合] [键值对集合]
List Set
SortedSet
有序
唯一
SortedSet接口
- TreeSet:
- 特点:有序(自动升序排序) 唯一
- 数据结构:二叉树
- TreeSet1:基本用方法及特点
- 创建对象:TreeSet<泛型> set = new TreeSet<>();
- 添加元素:set.add(元素)
- Collections.addAll(集合,元素,元素...);//自动升序排序
- 得到集合大小:set.size()
- 判断集合是否包含:set.contains(元素)
- 删除元素:set.remove(元素)
- 清空集合:set.clear()
- 遍历:foreach + 迭代器
- 得到集合里面的第一个元素:set.first()
- 得到集合里面的第一个元素并且删除:set.pollFirst()
- 得到集合里面的最后一个元素:set.last()
- 得到集合里面的最后一个元素并且删除:set.pollLast()
- TreeSet2:任何引用数据类型如果想要装进TreeSet集合都需要这个类型会排序有比较规则
类型 implements Comparable<要比较的对象> -> 覆盖:compareTo()
- TreeSet3:当我们想要按照多个属性综合排序的时候优先比较什么属性就描述当属性不一样的话...
- TreeSet4:当我们在覆盖compareTo()方法的时候尽量保证有机会返回0 否则add(元素):不能保证元素的唯一性根据Java的约定,当两个对象相等时,compareTo()方法应该返回0。这意味着在覆盖compareTo()方法时,我们应该保证对于相等的对象,有机会返回0。这样可以确保TreeSet中的元素按照自然顺序进行排序,并且保证元素的唯一性。
- remove(元素):永远删除失败
- contains(元素):永远返回false
- TreeSet5:当一个对象已经添加进TreeSet集合之后不要随意的修改那些参与排序的属性值
- 如果在添加之后想要修改的话:删除+修改+添加
- 如果要修改的属性没有参与排序的话:直接修改
# day18
- TreeSet集合
TreeSet集合
- 创建对象:TreeSet<泛型> set = new TreeSet<>();
- 添加元素:set.add(元素) Collections.addAll(集合,元素,元素...);
- 判断是否包含:set.contains(元素)
- 删除元素:set.remove(元素)
- 得到第一个元素:set.first()
- 得到第一个元素并且删除:set.pollFirst()
- 得到最后一个元素:set.last()
- 得到最后一个元素并且删除:set.pollLast()
- 遍历
- foreach
- 迭代器
- 如果引用数据类型如果想要装进TreeSet都要求当前的类型会排序有比较规则,需要覆盖其compareTo方法,具体实现如下compareTo方法永远返回int类型
- class Student implements Comparable<Student>{
- @Override
- public int compareTo(Student oldStu)
- //return this.namepareTo(oldStu.name)->string类型比较需要compareTo方法
- return this.age - oldStu.age;
- }
- }
- 如果想要按照多个属性综合排序的话 优先比较什么属性就描述如果这个属性不一样的话...
- if(this.score != stu.score)return stu.score - this.score;//降序
- if(this.age != stu.age)return this.age - stu.age;//升序
- if(!this.name.equals(stu.name))return this.namepareTo(stu.name);
- return 0;
- 在覆盖compareTo尽量保证这个方法有机会返回0
- add() : 保证其唯一
- remove() : 保证能够移除某个元素
- contains() :保证contains方法能够返回true
-如果一直return1,就会让add()方法失去其唯一性,因为1>0,元素会一直往右边排列,remove方法将会失效,因为一直往右边去寻找,一直找不到,contains方法会一直返回false,因为一直往右边去寻找,一直找不到
- 在遍历的时候想要删除:car.remove()
- 如果一个对象已经装进TreeSet集合之后 想要修改参与排序的属性:删除 + 修改 + 添加,迭代器不能一边删除一边向迭代器里面增添元素,需要另外一个集合做中介
- 第一个添加进集合里面的元素在某个时间段内是根节点,随着元素的增多根节点可能会发生改变,TreeSet底层基于平衡二叉树
- 如果想要脱离开一个类制定它的排序规则 需要比较器Comparator,可以将他写成单例模式
class BJQ implements Comparator<Student(需要比较的类型)>{
@Override
public int compare(Student newStudent, Student oldStudent){——>此处为两个参数
return oldStudent.score - newStudent.score;
}
}
比较器
class BJQ implements Comparator<Teacher>{
private BJQ(){}//私有化构造方法,防止外界随意的创建对象
private static BJQ bb = new BJQ();//创建一个私有的 静态的 属于本类类型的对象
public static BJQ getBB(){//提供一个公共的 静态的 返回本类对象的方法
return bb;
}
@Override
public int compare(Teacher newTeacher,Teacher oldTeacher){
if(newTeacher.getSalary()!=oldTeacher.getSalary())return (int)(newTeacher.getSalary()-oldTeacher.getSalary());
if(newTeacher.getAge()!=oldTeacher.getAge())return newTeacher.getAge()-oldTeacher.getAge();
if(newTeacher.getName().equals(oldTeacher.getName()))return newTeacher.getName()pareTo(oldTeacher.getName());
return 0;
}
}
TreeSet<Teacher> set = new TreeSet<>(BJQ.getBB());//main()方法接收一下
/**
键值对的通用用法:
创建对象:HashMap<主键泛型,泛型> map =new HashMao();
添加元素:map.put(主键,值); 两个值,成对添加
无法多元素添加
map1.putAll(map2):将两个集合合并
集合大小:map.size()
通过主键得到值对象:map.get(主键)
通过主键得到值对象:map.containsKey(主键);
判断某个值是否存在:map.containsValue(值);
通过主键删除一条记录:map.remove()
toString覆盖{主键=值,主键=值,主键=值......}
清空集合:map.clear()
是否为空map.isEmpty()
Map方法通用遍历方式:
1、得到所有主键视图
Set<主键> set = map.keySet():得到MAp集合里的主键视图
将Map集合转换为单值集合,再用单值集合的遍历方法做
2、得到所有值的视图
Collection<值的泛型> cs = map.values() : 通过map集合得到所有的值的视图
3、得到所有的记录【主键+值】
Set<记录> set = map.entrySt() : 返回主键和值的对应关系的视图 entry(记录)
Set<Map.Entry<主键泛型,值泛型>> set = map.entrySet()
entrySet() 得到Map集合里面的每条记录【主键+值】
记录:无序唯一
通过记录得到主键:getKey()
通过记录得到值:getValue()
修改值对象:setValue()
Set<Map.Entry<主键,值>> set = map.entrySet();
for(<Map.Entry<主键,值> x : set){
String key = x.getKey();
Integer value = x.getValue();
if(){
x.setValue();
}
}
主键遇到重复元素的时候,map默认将值替换
hash码值,nazhe hash 无序顺序可控用hzshset算
Syetem.out.iimport<> int
# day19
Map集合
Map:键值对类型的集合
每次往集合里面添加一对(即两个元素)元素-》key[主键]=value[值] 需要保证主键的唯一性
- 所有Map集合通用的方法
- 如何创建对象:HashMap<主键,值> map = new HashMap<>();
- 如何添加元素:map.put(主键,值),不能一次性增添多对元素,只能一次性添加一对元素,map1.putAll(map2),将两个map集合合并
- 得到集合大小:map.size()
- 判断某个主键是否存在:map.containsKey(主键),返回boolean类型
- 判断某个值是否存在:map.containsValue(值),返回boolean类型
- 删除一对信息:map.remove(主键)
- 通过主键得到值对象:map.get(主键)
- 清空集合:map.clear()
- 判断集合是否为空:map.isEmpty()
- 所有Map集合通用的遍历方式:*********
- 通过map集合得到所有的主键视图:
- Set<主键泛型> set = map.keySet();
- 遍历集合得到所有的主键
- 通过主键得到值对象:map.get(x)
- 通过map集合得到所有的值视图:
- Collection<值> cs = map.values();
- 遍历集合得到所有的值
- 通过map集合得到所有的记录[主键+值]:
- Set<Map.Entry<主键,值>> set = map.entrySet();
- 遍历集合得到所有的记录x:主键+值
- 通过记录得到主键:x.getKey()
- 通过记录得到值:x.getValue()
- 修改值对象:x.setValue(值)
- HashMap:底层基于哈希表实现的,默认分16个小组,每对元素[主键+值]应该去到哪一个小组根据主键的哈希码值决定 当来到某个小组之后发现该小组有元素的哈希码值和新来主键的哈希码值一样 需要== 和equals()
- HashMap底层的:
- put(主键,值) - get(主键) - remove(主键) - containsKey(主键)
- 底层尊重hashCode() == equals()比较机制
- 所有Map集合当主键遇到重复元素的时候 主键不变,值替换
- 面试题:
- Hashtable和HashMap之间的区别?
(1)同步线程不同
- Hashtable同一时间允许一个线程进行访问 效率较低 但是不会出现并发错误
- HashMap同一时间允许多个线程进行访问 效率较高 但是可能会出现并发错误
- jdk5.0开始 集合的工具类里面提供一个方法 将线程不安全的HashMap变成线程安全的MapJ集合 于是Hashtable渐渐被淘汰了
(2)分组组数不同
- Hashtable默认分11个小组 程序员可以随意的指定
- HashMap默认分16个小组 程序员可以随意的指定 但是最终一定会变成2的n次方数
(3)对null容忍度不同
- Hashtable无论是主键还是值对象 都不可以传null 否则出现空指针异常
- HashMap无论是主键还是值都可以传null 由于主键是唯一的 所以主键只能传一个null,但是值可以传入无数个
(4)出现的版本不同
Hashtable since jdk1.0、
HashMap since jdk1.2
- Hashtable 、HashMap、 ConcurrentHashMap之间的区别?
- Hashtable底层所有的方法都加上synchronized(加锁) 只要有一个线程进入哈希表 将整个哈希表全部加锁,同一时间只允许一个线程进行访问 效率极低但是很安全
- HashMap为了追求高效率不再加锁 那么就可以出现并发修改异常
- ConcurrentHashMap采用锁分离机制,将锁的力度降低,如果一个线程进入哈希表的某个小组 仅仅对小组进行加锁 如果新来的线程也想要访问该小组就需要等待,如果新来的线程去到其他没有加锁的小组 可以直接访问,同一时间可以会有多个线程一起进行访问,效率高也比较安全
- HashMap在jdk7.0前后的底层变化?
- HashMap底层基于哈希表实现的
- jdk7.0及之前 哈希表由数组 + 链表组成
- 数组用来装表头信息 可以帮助元素快速的定位应该去到的小组在哪
- 组内在存储元素的时候为了添加/删除元素方便 采用是链表数据结构
- 采用头插法
- jdk8.0开始 哈希表由数组 + 链表 + 二叉树组成
- 数组: 存储表头信息 帮助元素快速定位应该去到哪一个小组
- 组内用链表数据结构存储 但是当组内元素>8个元素的时候 底层由链表转换成二叉树[提高效率]
- 采用尾插法
- HashMap底层分组为什么一定要是2的n次方数?
- 计算小组:哈希码值 % 分组组数
- 优化 :哈希表值 & (分组组数-1)
- 只要分2的n次方数个小组 那么在计算元素该去哪一个小组的时候就可以通过&去计算 &的效率比%效率高
- HashMap是不安全的集合 在项目开发的时候可以使用哪些类取代?
Hashtable、ConcurrentHashMap、Map map = Collections.synchronizedMap(HashMap对象)
TreeMap:
- TreeMap底层基于二叉树实现的 每对元素[主键+值]应该放进左子树/右子树 根据主键和老元素的主键做compareTo()/compare() 看结果
[< 0 ]新来这对元素放在左边 [= 0 ]主键不变 值替换 [> 0 ]新来这对元素放在右边
TreeMap底层的: put(主键,值) get(主键) remove(主键) containsKey(主键)
底层尊重compareTo()/compare()
Collections类常用的方法
- Collections类针对List集合提供的方法:
- Collections.sort(List):按照泛型类进行排序 -》 自然排序
- Collections.sort(List,比较器);按照比较器的对象排序 -》 定制排序
- list.sort(比较器)---》定制排序
- Collections.reverse(List);翻转List集合元素
- Collections类针对所有的单值集合都可以使用的方法:
- Collections.addAll(单值集合,元素,元素...);一次添加多个元素
- Collections.max(单值集合):按照泛型类排序规则得到最大值,存在返回值,打印的时候打印返回值,不要打印集合 -》 自然升序排序
- Collections.max(单值集合,比较器)按照比较器的规则排序得到最大值,存在返回值,打印的时候打印返回值,不要打印集合 -》 定制升序排序
- Collections.min(单值集合):按照泛型类排序规则得到最小值,存在返回值,打印的时候打印返回值,不要打印集合-》 自然降序排序
- Collections.min(单值集合,比较器):按照比较器规则进行排序得到最小值,存在返回值,打印的时候打印返回值,不要打印集合 -》 定制降序排序
- Collections.frequency(单值集合,元素):得到该集合中指定元素出现的个数
如何对TreeSet集合排序:
TreeSet<泛型类> set = new TreeSet<>();
TreeSet<泛型类> set = new TreeSet<>(比较器);比较器优先级高于泛型的排序
如何对ArrayList集合排序:
ArrayList<> list = new ArrayList<>();//默认添加顺序
Collections.sort(list);//自然排序
Collections.sort(list,比较器);
如何对HashSet集合排序:
如何得到ArrayList/HashSet/TreeSet集合里面的最大值:
Collections.max(单值集合);//自然排序
Collections.max(单值集合,比较器);//定制排序
# day20
- Optional类
- Lambda表达式
- Stream流
Optional类
jdk8.0出现的一个新类 表示容器类 专门用来解决空指针异常的类 可以使代码变得更加简化而且健壮
- 如何将一个对象装进Optional容器里面
- String str = ...;
- Optiona<String> op = Optional.of(str);//参数是null 直接出空指针
- Optional<String> op = Optional.ofNullable(str);//即使参数为null也不会出现空指针异常 但是容器不会装值
- 判断容器类里面是否存在值
- op.isPresent() -> boolean,搭配get使用
- 如果想要从容器里面取值
- op.get() -> 泛型类
- 容器里面如果有值 利用get()可以将值取出来
- 容器里面如果没有值 使用get()出现NoSuchElementException
- 如果容器里面有值 直接返回容器里面的值 如果容器里面没有值 那么提供一个默认值
- 数据类型 x = Optional.ofNullable(str).orElse(默认值);
- ofNullable参数类型需要和orElse的参数类型一致
Lambda表达式
使用前提是函数式接口
jdk8.0出现的一个新语法 可以使代码变得非常简洁而且专业
- jdk8.0出现新的操作符 ->箭头操作符 ,将整个语句分为两个部分
- 左侧:要覆盖方法的参数列表 - 右侧:表示lambda体 写具体的执行步骤
- 在调用方法的时候,如果方法的参数是一个函数式接口,都可以使用lambda表达式
- 函数式接口:接口里面只有一个抽象方法 -普通接口:多个抽象方法
- Lambda表达式需要注意:
- 左侧参数列表如果只有一个参数的话 ()可以省略 但是如果是无参/多参 ()不能省略
- 左侧参数列表的数据类型可以省略 jdk7.0开始泛型类可以自动推断
- 右侧lambda体如果只有一句话{}和return可以省略,如果lambda体多个语句 {}和return不能省略
- jdk8.0单值[list,set,soredSet]集合新增的方法:
- forEach((x) -> void):遍历集合每个元素,对每个元素进行…..操作,需要返回值为void类型
- removeIf((x) -> boolean):删除集合里面符合条件的元素,返回的boolean类型为删除的条件
-jdk8.0对Map集合新增的方法:
- forEach((k,v) -> void):遍历map集合得到每对元素,对每对元素进行…..操作,返回值为void类型
-jdk8.0对List集合的排序方法:
-list.sort((x,y) -> 排序规则)
- jdk8.0新增4大函数式接口:
- Consumer[消费型接口]
- 抽象方法:accept(x) -> void(forEach)
- Predicate[断言型接口]
- 抽象方法:test(x) -> boolean(removeIf)(filter)
- Function[函数型接口]
-抽象方法:apply(x) -> R(map)
-Supplier[供给型接口]
-抽象方法:get() -> R generate(() -> ...)无限流
方法引用:(idea自动转换) [语法糖]
- 以前:
- 对象.实例方法()
- 类名.静态方法()
- Jdk8.0开始 现在:
- 对象::实例方法 -> System.out::println
- 必须满足
- 抽象方法的参数列表个数和类型必须和调用实例方法的参数一致
- 抽象方法的返回类型和调用实例方法的返回类型一致
- 类名::静态方法 -> String::valueOf-
- 必须满足
- 抽象方法的参数列表个数和类型必须和调用静态方法的参数一致
- 抽象方法的返回类型和调用静态方法的返回类型一致
- 类名::实例方法 -> Integer::compareTo
- 必须满足
- 抽象方法的参数列表个数必须比调用实例方法的参数多1个 且抽象方法的第一个参数可以作为实例方法的调用者
- 抽象方法的返回类型和调用实例方法的返回类型一致
- 类名::new -> Student::new
- 必须满足
- 抽象方法的参数列表个数和类型必须和调用构造方法的参数一致
- 抽象方法的返回类型和调用构造方法的返回类型一致
##### Stream类: Stream类是jdk8.0出现的一个新类,他可以对数据进行流式处理,可以从数组/集合中读取数据进行一系列处理,包括查找/过滤/映射...可以让代码变得非常简化而且优雅.
-将集合装入流中:Stream<元素泛型> ss = 单值集合.stream(); (只能是单值集合)
-将数组装入流中:Stream<泛型> ss = Arrays.stream(数组对象)
-将零散数据装入流中:Stream<泛型> ss = Stream.of(元素,元素……..)
- 中间操作的方法(依然返回流):
- filter((x) -> boolean):Predicate过滤流(相当于if)里面符合条件的元素装在流里面,返回新流
- limit(long n):截断流 截取流里面前n个元素,返回新流
- generate(() -> R):创建无限流对象,返回新流
- skip(long n):丢弃前n个元素将剩下的元素装进新流里面,返回新流
- distinct():去除流里面的重复元素 底层尊重hashCode() == equals(),返回新流
- map((x) -> R):Function参数接收一个函数 底层会将该函数应用到每一个对象上(将流里面每个对象映射为另外一个对象),返回新流
- sorted():对流里面的元素进行自然排序[按照泛型类排序规则排序] ,返回新流
- sorted((x,y) -> int):Comparator对流里面的元素按照比较器的规则进行排序,返回新流
Stream流里面所有的中间方法必须配合终端方法才能执行 如果仅仅调用中间方法不调用终端方法的话 那么中间方法不会执行 -》 惰性求值
Stream类:对数据流式化处理,
18个方法
中间操作的方法:
fiIter(Predicate):过滤流里面的符合条件的元素
先将元素装流里面,集合调用stream,按照集合的顺序将元素装进Stream流里面
Stream<泛型> ss = list.stream(); 将集合装成流对象 需要导包
ss.filter((x)-> x<60);
Stream类类面所有中间操作的方法必须配合终端方法才能执行
list.stream() 将集合转为流
.filter((x)-> x<60) 判断
.forEach((x)-> 打印语句);
limit(long n)截断流,截取流里面的前n个元素
list.stream() 将集合转为流 中间方法可以有n个,但终端方法只有一个
.filter((x)-> x<60); 过滤 判断
.limit(3)
.forEach((x)-> 打印语句);
skip()丢弃前n个,将剩下的元素组成新流
list.stream(3) 将集合转为流
.skip()
.forEach((x)-> 打印语句);
distinct() 无参去重,将流里面的重复元素删掉
list.stream() 将集合转为流 中间方法可以有n个,但终端方法只有一个
.filter((x)-> x<60); 过滤 判断
.distinct()
.forEach((x)-> 打印语句);
map() 映射:参数接受一个函数,会把该函数应用到每一个对象身上
list.stream()
.map((x)-> x.toUpperCase())
.forEach((x)-> 打印语句);
sorted() 无参数,根据泛型进行排序,自然排序,需要有比较规则
list.stream()
.sorted()
.forEach((x)-> 打印语句);
sorted(Comparetor比较器) 对流里面的进行定制排序
list.stream()
.sorted((x,y)-> x.length() -y.length())
.forEach((x)-> 打印语句);
*/
# day21
Stream流
- Date/Calendar/LocalDate/LocalTime/LocalDateTime时间类
- 枚举类
##### Stream流:提供一些列的方法可以对数据进行流式处理
- 如何将集合转换成流
- 集合对象.stream()
- 如何将数组转换成流
- Arrays.stream(数组对象)
- 将一组零散的数据放入流里面
- Stream.of(元素,元素,元素...)
- 中间操作的方法(依然返回流):
- filter((x) -> boolean):Predicate过滤流(相当于if)里面符合条件的元素装在流里面,返回新流
- limit(long n):截断流 截取流里面前n个元素,返回新流
- generate(() -> R):创建无限流对象,返回新流
- skip(long n):丢弃前n个元素将剩下的元素装进新流里面,返回新流
- distinct():去除流里面的重复元素 底层尊重hashCode() == equals(),返回新流
- map((x) -> R):Function参数接收一个函数 底层会将该函数应用到每一个对象上(将流里面每个对象映射为另外一个对象),返回新流
- sorted():对流里面的元素进行自然排序[按照泛型类排序规则排序] ,返回新流
- sorted((x,y) -> int):Comparator对流里面的元素按照比较器的规则进行排序,返回新流
- 终端方法
- forEach((x) -> void):Consumer遍历流里面的每一个元素,对流里面每个元素进行…处理
- anyMatch((x) -> boolean):Predicate判断流里面是否有一个元素符合条件,返回boolean类型
- allMatch((x) -> boolean):Predicate判断流里面是否所有元素都符合条件,返回boolean类型
- noneMatch((x) -> boolean):Predicate判断流里面是否没有元素符合条件,返回boolean类型
- findFirst():得到流里面的第一个元素,返回类型为Optional,后续可以用get方法取值
- reduce((sum,x) -> sum + x):BiFunction将流里面的多个值归约合并成一个值,求和用, 返回类型为Optional,后续可以用get方法取值(隐式的for循环),必须保障输入的为数字,或者是取得后一个元素(reduce((x,y) -> y)),
- count():得到流的个数,返回long类型
- max((x,y) -> int):Comparator按照比较器得到流里面的最大值,默认列表最后一个元素,升序排序比较合适,返回类型为Optional,后续可以用get方法取值
- min((x,y) -> int):Comparator得到流里面的最小值,默认列表第一个元素,降序排序比较合适,返回类型为Optional,后续可以用get方法取值
- collect():将流里面的元素收集起来
- Collectors.toList(),用List<>接收
- Collectors.toSet(),用Set<>接收
- Collectors.toMap(()->xx,()->xx),用Map<>接收,主键不重复
- Collectors.toMap(()->xx,()->xx,(oldKey,newKey)->newKey),用Map<>接收,主键重复
- Collectors.toCollection(HashSet :: new)
- 四大函数式接口:
- Consumer[消费型接口]
- 覆盖:accept(x) -> void
- Predicate[断言型接口]
- 覆盖:test(x) -> boolean
- Function[函数型接口]
- 覆盖:apply(x) -> R
- Supplier[供给型接口]
- 覆盖:get() -> R
时间类
Date类
jdk1.0出现的时间类 java.util包下面 大部分内容已经过时 且不支持国际化 不安全
- 如何得到当前的时间:
- Date dd = new Date(); - Date dd = new Date(long time);
- 如何将Date转换成String(格式化时间)
- Date dd = new Date();
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- String time = sdf.format(dd);
- 如何将字符串转换成Date类:
String time = "2023-5-21 13:22:51";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dd = sdf.parse(time);
Calender 日历类
since jdk1.1 功能比Date类强大 不安全
- 如何获得当前的时间 Calendar cc = Calendar.getInstance();//Calendar抽象类,不能new对象
- 如何得到年月日时分秒
System.out.println(cc.get(1));
System.out.println(cc.get(Calendar.YEAR));
1:年 2:月份 5:号 7:周几 11:小时 12:分钟 13:秒钟
- 如何修改年月日时分秒
cc.add(5,3); cc.add(Calendar.DAY_OF_MONTH,3);
- 如何将Calendar转换成String类(格式化时间)
Calendar cc = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(cc.getTime());
LocalDateTime
jdk8.0出现的新的时间类 java.time包下面 安全
- LocalDate:得到年月日 - LocalTime:得到时分秒 - LocalDateTime:当地日期时间
- 如何得到当前的日期 LocalDate ld = LocalDate.now();
- 如何指定的日期 LocalDate ld = LocalDate.of(2023,4,5);
- 如何得到当前的年月日时分秒 LocalDateTime ldt = LocalDateTime.now()
- 如何得到指定的年月日时分秒 LocalDateTime ldt = LocalDateTime.of(2023,4,12,23,11,23);
- 如何得到年月日时分秒 ldt.getYear(); ldt.getMonth(); ldt.getDayOfMonth();
- 如何修改年月日时分秒 Idt = ldt.plusYears(5);//5年后 Idt = ldt.plusMonths(3);//3月后
- 判断时间A是否在时间B之前 LocalDateTime对象.isBefore(LocalDateTime对象)
- 判断A时间是否在B时间之后 LocalDateTime对象.isAfter(LocalDateTime对象)
- 如何记录两个时间差
Duration dd = Duration.between(时间1,时间2);
System.out.println(dd.toDays());
System.out.println(dd.toHours());
- 如何格式化时间 时间类转换成字符串类
LocalDateTime ldt = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String time = dtf.format(ldt);
- 如何格式化时间 字符串转换成时间类
String time = "2023-12-30 21:55:12";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy_mm_dd HH:mm:ss");
LocalDateTime ldt = LocalDateTime.parse(time,dtf);
枚举类
jdk5.0出现的新类型 当一个类的对象是有限个确定的非常适合枚举类
class Student{} -> 普通类
class Sun{} -> 单例模式
class Week{} -> 7 -> 枚举类
class Season{} -> 4 -> 枚举类
//Java中所有的枚举类都默认继承Enum
toString()在Enum类已经覆盖过的,Enum-》toString() -> 打印对象显示:枚举常量的名字
在Java中一个类只能继承一个类,所以枚举类继承Enum之后不能在继承其他的类,但是枚举类可以实现接口
(1)将枚举类对象装进数组里面:枚举类[] data = 枚举类名.values();
例:Season[] data = Season.values();
Arrays.stream(data).forEach((x) -> System.out.println(x));
(2)将枚举类对象装进集合里面:EnumSet<枚举类> set = EnumSet.allOf(枚举类名.class);
例:EnumSet<Season> set = EnumSet.allOf(Season.class);
set.forEach((x) -> System.out.println(x));
(3)将字符串转换成枚举对象:String str = "xxx"; 枚举类 对象 = 枚举类名.valueOf(str);
例:String str = "abc";
Season xx = Season.valueOf(str);
System.out.println(xx);
(4)将枚举对象转换成字符串:String x = 枚举对象+""; String y = 枚举对象.name()
例:Season ss = Season.SUMMER;//ss = SUMMER
String name = ss.name();//setName()
System.out.println(ss + " " + name);
(5)得到枚举对象的下标: int x = 枚举对象.ordinal();
(6)比较两个枚举对象是否一样:x.equals(y),底层比较 == 比较地址
(7)比较两个枚举大小:xpareTo(y),比较下标的大小
注解
内置注解:注解作用在其他类、方法、属性
三大内置注解:
@Override:方法覆盖
@Deprecated:当前方法、类、属性已经过时
@SuppressWarnings("xxxx"):忽略xxxx警告
元注解:作用在其他注解上
四大元注解:
(****)@Target:描述当前被修饰的注解(内置注解)可以作用在谁的身上->从enum ElementType中选择
(****)@Retention:描述当前被修饰的注解采用的生命周期->从enum RetentionPolicy中选择
@Documented:描述当前被修饰的注解能生成在帮助文档里面
@Inertied:描述当前被修饰的注解可以被继承
//用于描述注解的类型 -》 用在谁的上面
public enum ElementType {
TYPE,//表示该注解用于 类 接口 枚举 包括注释类型
FIELD,//字段声明 包括枚举常量
METHOD,//方法声明
PARAMETER,//参数声明
CONSTRUCTOR,//构造方法声明
LOCAL_VARIABLE,//局部变量声明
ANNOTATION_TYPE,//注释类型声明
PACKAGE,//包声明
}
//用于描述每个注解的策略 -》作用域
public enum RetentionPolicy {
//注解信息仅存于编译器处理期间 编译器处理完就没有该注解信息了 比如@Override
SOURCE,
//编译器将注解信息存储在类的.class文件中 属于默认行为
//但是不能被反编译
CLASS,
//编译器将注解信息存储在class文件中 可以被JVM读入
//该注解会生成在.class文件里面 并且可以被反编译 -》 注解
RUNTIME
}
本文标签: MyselfNotescoreJavabysir
版权声明:本文标题:MyselfNotes_coreJava_by_sir.w 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1725925847a1049355.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论