第一章 计算机基础
jiva技术架构
- JavaSE Java Standard Edition Java标准版:桌面型应用程序
- JavaEE Java Enterprise Edition Java企业版:服务器应用程序
- JavaME Java Micro Edition Java微型版:嵌入式应用程序
java最大的特点——跨平台
跨平台的意思就是说,一个软件可以在多个平台上运行,而不用更改软件的内容。
是因为JVM的功劳:JVM(Java Virtual Machine)Java虚拟机。
Java源代码文件后缀名为xxx.java 所编译出来的二进制文件后缀名为xxx.class
JVM主要负责将java语言的字节码文件转换为本地操作系统指令的一个工具软件。 所以,最终是字节码文件在跨平台!
JDK的下载与安装
- 先登录注册Oracle
- 去Oralce官网下载JDK,最新JDK15,我们目前用JDK8 https://www.oracle.com
- 点击Products
- 点击SoftWare下的Java
- 右上角DownloadJava
- 找到JavaSE8 点击JDK Download
- 下拉 在下载列表中选择Windows X64
- 双击打开jdk安装程序
- 点击下一步
- JDK不需要更改目录 直接下一步
- JRE不需要更改目录 直接下一步
- 安装完成 点击关闭即可
- 验证jdk是否安装成功
- win+r 打开cmd 输入 java -version
java version "1.8.0_77" `
`Java(TM) SE Runtime Environment (build 1.8.0_77-b03) `
`Java HotSpot(TM) 64-Bit Server VM (build 25.77-b03, mixed mode)
配置path环境变量
- 复制jdk中bin目录的绝对地址 C:\Program Files\Java\jdk1.8.0_77\bin
- 右键此电脑 点击属性
- 点击高级系统设置
- 点击环境变量
- 系统变量中选择Path
- 右上角 新建 将地址复制进去即可
- 一路确定出去
- 重启cmd 再去尝试javavc java
VSCode修改方式
VSCode代码编辑器 https://code.visualstudio.com/
汉化:左下角管理 Extension 搜索Chinese 选择Chinese中文简体汉化包 点击绿色install 右下角提示 重启 重启即可
主题:管理 颜色主题 自选
编码:管理 设置 文本编辑器 文件 Encoding 选择gbk结尾
字体:管理 设置 文本编辑器 字体 font size
关联代码所在的文件夹:文件 打开文件夹 选择JavaDay01
运行java程序
步骤一:新建Java源代码文件并写入类
点击新建文件按钮,输入Java源代码文件名称和后缀名,例如 JavaDay01.java 在文件中写入如下代码:
public class JavaDay01 {
}
注 : public class Sample01 中的 Sample01 是类名,而且在Java源代码中,可以存在多个类,但是 最多只能有一个public开头的类,并且该类的类名必须与文件名保持一致!!! |
---|
步骤二:编译该代码文件 |
打开控制窗口cmd,将目录切换到javaDay01目录下
C:\Users\HX>cd Desktop\\xuexi\\javademo
再输入 javac Sample01.java 对源代码文件进行编译
C:\Users\HX\Desktop\xuexi\javademo<javac JavaDay01.java
如果没有任何输出,则表明编译成功,并生成同名的字节码文件 Sample01.class
步骤三:运行该字节码文件
输入 java javaday01即可
C:\Users\HX\Desktop\xuexi\javademo<java JavaDay01
第二章 基本数据与运算
关键字
关键字是指被高级编程语言赋予特殊含义的一些单词,关键字一般都是由小写字母组成。好比是汉 语当中的一些专有名词:北京,天安门,兵马俑。不能乱用。
- 用于定义数据类型的关键字:byte short int long float double char boolean void class interface
- 用于定义数据类型值的关键字:true false null
- 用于定义流程控制语句的关键字:if else switch case default while do for break(退出当前循环) continue(结束当前循环) return
- 用于定义访问权限修饰符的关键字:public protected private
- 用于定义继承关系的关键字:extends(继承) implements(实现接口)
- 用于定义实例对象的关键字:new this super instanceof
- 用于定义函数类型的关键字:static final abstract synchronized(同步线程)
- 用于处理异常的关键字:try catch finally throw throws
- 用于包的关键字:package import
- 其他的一些修饰关键字:native assert volatile transient
标识符
标识符指的是我们在程序中对变量、函数、类、接口、常量所定义的名称,也就是说这些名称是我 们自定义的。
标识符必须满足以下组成规则:
- 标识符可以由数字、字母、下划线 _ 、美元符 $ 组成
- 标识符不能以数字开头,当然下划线和美元符其实是可以开头的,但不推荐
- 标识符不能是关键字
- 标识符也不能是Java内置类的名称
- 标识符可以为任意长度,但必须是一个连续的词
- 标识符严格区分大小写
注释
注释是用于注解和说明程序的一些程序中的内置文本信息的,但这些内置文本不属于代码的范畴。 所以在对含有注释的源代码进行编译时,所生成的字节码中不含有注释。注释是给人看的!
注释主要有三种:
- 单行注释 //注释内容 直到换行为止
- 多行注释 /* 注释内容 内部可以进行换行*/
- 文档注释 /** 注释内容 内部可以进行换行 */ :文档注释可以被编译器识别,并生成相应 的程序说明书。对某一个类进行文档生成时,该类必须是public型
常量与进制
常量就是指在程序中直接出现的一些数据,也叫字面量
常量都有哪些:
- 整数常量
- 小数常量
- 字符常量:由一个字母、数字、符号被单引号( ‘’ )标识的数据
- 字符串常量:由若干个字母、数字、符号被双引号( “” )标识的数据
- 布尔类型常量
- null常量
public class Sample {
public static void main(String[] args) {
//整数常量
System.out.println(10); //十进制整数
System.out.println(0b1001); //二进制整数 打印出来是十进制
System.out.println(0123); //八进制整数
System.out.println(0xAF3); //十六进制整数
//小数常量
System.out.println(3.14);
System.out.println(5.234e3);
System.out.println(1.2e-3);
//字符常量
System.out.println('a');
//System.out.println('ab'); ERROR
System.out.println('9');
//System.out.println('12'); ERROR
System.out.println('我');
System.out.println(' ');
//System.out.println(''); ERROR
//System.out.println('''); ERROR
System.out.println('\''); //打印 '
System.out.println('\n'); //打印 换行
System.out.println('\t'); //打印 缩进
//字符串常量
System.out.println("abcd");
System.out.println("a");
System.out.println(""); //字符串空串 vs null真空
System.out.println("\"");
//布尔常量
System.out.println(true);
System.out.println(false);
}
}
原反补的转换
原码
转换 当x 大于0时 x=x
当x大于0且小于1时 x=x
例如 0.1111=0.1111
当x为整数时 x=x
例如 01111=01111
当x 小于0时 x= 1-x=1+|x|
当x为小数时 x=(2-2^(-n))+x
例如 1.1111=1.0000
当x为整数时 x=2n-x=2n+|x|
例如 11111=11111
反码
转换 当x 大于0时 x=x
当x大于0且小于1时 x=x
例如 0.1111=0.1111
当x为整数时 x=x
例如 01111=01111
当x 小于0时
当x为小数时 x=(2-2^(-n))+x
例如 1.1111 = 1.0000
当x为整数时 x=(2^(n+1)-1)+x
例如 11111= 10000
补码
转换 当x 大于0时 x=x
当x大于0且小于1时 x=x
例如 0.1111=0.1111
当x为整数时 x=x
例如 01111=01111
当x 小于0时
当x为小数时 x=2+x=2-|x|
例如 1.0001=1.1111
当x大于1时 x=2(n+1)+x=2(n+1)-|x|
例如 11110=10010
移码
补码符号位相反即可
例题
真值 | 原码 | 反码 | 补码 |
---|---|---|---|
+70 | 01000110 | 010000110 | 01000110 |
-70 | 11000110 | 10111001 | 10111010 |
-0.875 | 1.1110 | 1.0001 | 1.0010 |
0.875 | 0.1110 | 0.1110 | 0.1110 |
+0 | 0.0000 | 0.0000 | 0.0000 |
-0 | 1.0000 | 1.1111 | 0.0000 |
-1.0000 | 无法表示 | 1.1111 | 1.0000 |
变量
指的是变化的量
- 变量的本质就是在内存中程序所处的进程中的一个临时存储区域
- 该区域的存储值有限制的
- 该区域值的变化必须是同类型的或向下兼容的
- 该区域有其自身的物理内存地址-指针
- 该区域中 存储值的限制 和 数据的变化类型 由 数据类型 来决定
- 该区域中 其空间的分配 和 空间的物理内存地址 由计算机底层来决定
回顾一下指针
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0ilHrWwq-1631327940075)(/QWGC70%5DWXPY%5BG@@XRPT2XOO.png)]
#include<stdio.h>
void main() {
int a = 3; //创建一个普通的整型变量 存3这个常量
int* b; //创建一个一重指针变量 存的是a变量的地址
b = &a;
int** c; //创建一个二重指针变量 存的是b变量的地址
c = &b;
printf("a的地址:%d\n",&a); //打印a的地址 0x123
printf("a的内容:%d\n",a); //打印a空间的内容 3
printf("b的地址:%d\n",&b); //0x456
printf("b的内容:%d\n",b); //0x123
printf("拿着b的内容去找变量a:%d\n",*b); //3
printf("c的地址:%d\n",&c); //0x789
printf("拿着c的内容去找变量b:%d\n",*c); //0x123
printf("拿着c的内容去找变量b,拿着b的内容去找变量a:%d\n",**c); //3
//printf("%d\n",*a);
printf("%d\n",*&*c); //0x123
printf("%d\n",&*&**&c); //0x456
}
结果如下
a的地址:6422300
a的内容:3
b的地址:6422296
b的内容:6422300
拿着b的内容去找变量a:3
c的地址:6422292
拿着c的内容去找变量b:6422300
拿着c的内容去找变量b,拿着b的内容去找变量a:3
6422300
6422296
数据类型
在Java当中,数据类型主要分为两大类:
-
基本数据类型:在变量的空间中存储数据
-
整形
- byte 1字节 2^8 256 -128~127 -2^7 ~ 2^7 - 1
- short 2字节 2^16 65536 -32768~32767 -2^15 ~ 2^15 - 1
- int 4字节
- long 8字节
-
浮点型
- float 4字节
- double 8字节
- 字符类型
- char 2字节
- 布尔型
- boolean 不确定
注:在常量中,整型常量默认int类型,小数常量默认是double类型
布尔类型,如果是单一变量的话,在JVM中true被认为是1 false被认为是0 所以是4字节存
如果是布尔类型数组的话,在JVM中true和false被认为是byte类型 1字节
- 引用数据类型:数据是在堆内存中存储,变量仅仅存放的是数据在堆内存中的地址
- 字符串
- 数组
- 对象
在Java中,但凡存储在堆内存中的数据,统称为对象
运算符
算数运算符
算数运算 符 | 含义 | 备注 |
---|---|---|
+ | 加法 | 1+2=3 如果加号左右有字符串 则加号为连接符 |
- | 减法 | 3-2=1 |
* | 乘法 | 3*2=6 |
/ | 除法 | 3/2=1 3.0/2=1.5 如果除号两边都是整数 结果为整数;有小数 结果为小 数 |
% | 取余 | 9%5=4 注意一点,如果前或后为负数(取余看被除数 取商看除数) |
a++ | 后置自增 | a自身加一,使用原来的值 |
++a | 前置自 增 | a自身加一,使用加之后的值 |
a– | 后置自 减 | a自身减一,使用原来的值 |
–a | 前置自 减 | a自身减一,使用加之后的值 |
赋值运算符
+= 加法赋值 a+=3 相当于 a=a+3
注意 赋值运算符只能用在变量身上
比较运算符
运算的结果为布尔类型
- / >大于
- / < 小于
- / >= 大于等于
- / <= 小于等于
- / != 不等于
逻辑运算符
- & 单与
- | 单或
- ^ 异或
- ! 非、
- && 双与
- || 双或
public class Sample {
public static void main(String[] args) {
int x = 0;
int y = 0;
System.out.println(x++ > 0 & y++ > 0);
System.out.println(x);
System.out.println(y);
x = 0;
y = 0;
System.out.println(x++ > 0 && y++ > 0);
System.out.println(x);
System.out.println(y);
//&& 如果左边为假 则右边不用执行
//|| 如果左边为真 则右边不用执行
//相同为假 不同为真
System.out.println(true ^ true);
System.out.println(true ^ false);
System.out.println(false ^ false);
System.out.println(false ^ true);
}
}
位运算符
- & 位与
- | 位或
- ^ 位异或
- />> 右移
- << 左移
public class Sample {
public static void main(String[] args) {
int x = 7;
int y = 12;
System.out.println(x & y);
/*
0111
1100 &
0100 4
*/
System.out.println(x | y);
/*
0111
1100 |
1111 15
*/
System.out.println(x ^ y);
/*
0111
1100 ^
1011 11
*/
System.out.println(x << 3);
/*
0111
0111000
x * 2^3
*/
System.out.println(56 >> 2);
/*
111000
1110
56 / 2^2
*/
}
}
注意 当 用 i<<1+1;时 系统会认为 i<<2;
public class weiyi{
public static void main(String []args){
int i=1;
i<<=1+1;
System.out.println(i);//4
i+=1;
System.out.println(i);//5
i=1;
i<<=1;
i+=1;
System.out.println(i);//3
}
}
三目运算符
数据类型 变量名 = 布尔表达式?值1:值2;
int number = 10 % 2 == 0? 10 : 2;
补充:变量交换问题
int a = 3; int b = 7;
方法一:
int c = a; a = b; b = c; System.out.println(a); System.out.println(b);
方法二
a = a + b; b = a - b; a = a - b; System.out.println(a); System.out.println(b);
方法三
a = a ^ b; b = a ^ b; a = a ^ b; System.out.println(a); System.out.println(b);
第三章 流程控制语句
if条件语句
单分支if语句
if(布尔类型表达式){
语句组;
}
双分支if-slse语句
if(布尔类型表达式){
语句组;
}else
多分支 if -else 语句
if (布尔表达式1) {
语句组A;
} else if (布尔表达式2) {
语句组B;
} else if (布尔表达式3) {
语句组C;
} else {
语句组D;
}
switch分支语句
与if分支语句一样,都是对条件的判断 。switch一般用在条件较多的情况下,但是有一个重要的细节,if语言可以对区间值或固定值进行判断,switch只能对固定值进行判断
switch(变量){
case 值1:
语句组A:
break;
case 值2:
语句组B;
break;
.......
case 值n: //if (变量==值n) {语句组N;}
语句组N;
default: // else {语句组N+1;}
语句组N+1;
break;
}
switch中的一些使用细节
- switch所传入的变量,char,byte,short,int,String或者枚举类型
- 值1,值2,一直到值n,这几个值必须是同一个数据类型的
- 当变量匹配的相关case的值的时候,执行case中的语句,直到遇到break结束,如果该case语句 中没有break,则继续向下执行,直到遇到另外一个break结束。
for循环语句
循环主要解决具有规律性的且具有重复性的代码问题,避免程序冗余
循环四要素
- 循环的初始化:循环的第1次执行从哪里开始
- 循环的继续条件:循环从当前轮是否向后执行下一轮
- 循环体:需要被循环执行的部分
- 循环的步长、周期:当前循环到下一轮循环之间的变化 我们常见的循环问题可以分为两大类:
- 已知循环次数的 一般用for语句做
- 未知循环次数但是已知循环结束条件 一般用while语句做
for (1循环的初始化;2.循环的继续条件;4.循环的步长) {
3.循环体
}
1-2-3-4-2-3-4-2-3-4-2不满足则结束循环
for循环演示
import java.util.Scanner;
public class Sample {
public static void main(String[] args) {
/*
*****
*/
for (int i = 1; i <= 5; i++) {
System.out.print("*");
}
System.out.println();
System.out.println("=============================");
/*
*****
*****
*****
*****
*/
for (int j = 1; j <= 4; j++) {
for (int i = 1; i <= 5; i++) {
System.out.print("*");
}
System.out.println();
}
System.out.println("=============================");
/*
*
**
***
****
*****
******
*******
*/
for (int line = 1; line <= 7; line++) {
for (int i = 1; i <= line; i++) {
System.out.print("*");
}
System.out.println();
}
System.out.println("=============================");
/*
******
*****
****
***
**
*
*/
for (int line = 6; line >= 1; line--) {
for (int i = 1; i <= line; i++) {
System.out.print("*");
}
System.out.println();
}
System.out.println("=============================");
/* i j
* 1 1
** 2 1 2
*** 3 1 2 3
**** 4 1 2 3 4
***** 5 1 2 3 4 5
****** 6 1 2 3 4 5 6 j <= i
***** 7 1 2 3 4 5
**** 8 1 2 3 4
*** 9 1 2 3
** 10 1 2
* 11 1 j <= 12 - i
j <= i && j <= 12 - i
*/
for (int i = 1; i <= 11; i++) {
for (int j = 1; j <= i && j <= 12 - i; j++) {
System.out.print("*");
}
System.out.println();
}
System.out.println("=============================");
/* i |i - 6|
* 1 -5
** 2 -4
*** 3 -3
**** 4 -2
***** 5 -1
****** 6 0
***** 7 1
**** 8 2
*** 9 3
** 10 4
* 11 5
*/
for (int i = 1; i <= 11; i++) {
for (int k = 1; k <= Math.abs(i - 6); k++) {
System.out.print(" ");
}
for (int j = 1; j <= i && j <= 12 - i; j++) {
System.out.print("* ");
}
System.out.println();
}
System.out.println("=============================");
/* j
* 1
* * 1 2
* * 1 2 3
* * 1 2 3 4
* * 1 2 3 4 5
* * 1 2 3 4 5 6
* * 1 2 3 4 5
* * 1 2 3 4
* * 1 2 3
* * 1 2
* 1
j == 1 j == i j + i == 12
*/
for (int i = 1; i <= 11; i++) {
for (int k = 1; k <= Math.abs(i - 6); k++) {
System.out.print(" ");
}
for (int j = 1; j <= i && j <= 12 - i; j++) {
if (j == 1 || j == i || j + i == 12) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}
while循环语句
while循环主要用于解决循环次数未知,但循环结束条件已知的情况。
while其实和for循环是可以相互转换的,是因为都逃不开循环四要素
for (int i = 1; i <= 5; i++) {
System.out.println(i);
}
可以转换为while循环
int i = 1;
while (i <= 5) {
System.out.println(i);
i++;
}
while的语法格式
1.循环的初始化
while (2.循环继续条件) {
3.循环体
4.循环的步长、周期
}
break、continue跳转语句
break在循环语句中叫做终止语句,终止的是break最近的一层循环
continue在循环语句中叫做跳过语句,跳过本次循环开启下一轮循环
public class Sample {
public static void main(String[] args) {
for(int j=0;j<2;j++){
for (int i = 1; i <= 5; i++) {
if (i == 3) {
break;
} else {
System.out.println(i);
}
}
}
//结果 1 2 1 2
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue;
} else {
System.out.println(i);
}
}
//结果 1 2 4 5
}
}
第四章 常用类
Math类
Math类是用于数学计算的一个工具类
对于工具类而言,里面的大部分成员都是静态的static
自带常量
- static double E;自然对数
- static double PI;圆周率
取整方法
- static double cell(double a);向上取整
- static double floor(double a);向下取整
- static long round(double a);四舍五入
三角函数
- static double sin(double a):正弦函数 参数是弧度值
- static double cos(double a):余弦函数
- static double tan(double a):正切函数
- static double toDegrees(double a):将弧度转角度
- static double toRadians(double angles):将角度转弧度
- static double asin(double a):反正弦函数
- static double acos(double a):反余弦函数
- static double atan(double a):反正切函数
‘指数函数
- static double pow(double a, double b):求a的b次幂
- static double sqrt(double a):求a的平方根
- static double cbrt(double a):求a的立方根
其他方法
- static double abs(double a):求a的绝对值
- static double hypot(double deltX, double deltY):返回 两点间距离
- static double max(a,b):返回a和b之间的最大值
- static double min(a,b):返回a和b之间的最小值
- static double random():返回[0,1)之间的随机小数
用法
public class Sample {
public static void main(String[] args) {
System.out.println(Math.E);//2.718281828459045
System.out.println(Math.PI);//3.141592653589793
System.out.println(Math.ceil(3.1));//4.0
System.out.println(Math.ceil(3.9));//4.0
System.out.println(Math.ceil(-3.1));//-3.0
System.out.println(Math.ceil(-3.9));//-3.0
System.out.println(Math.floor(3.1));//3.0
System.out.println(Math.floor(3.9));//3.0
System.out.println(Math.floor(-3.1));//-4.0
System.out.println(Math.floor(-3.9));//-4.0
System.out.println(Math.round(3.1));//3
System.out.println(Math.round(3.9));//4
System.out.println(Math.round(-3.1));//-3
System.out.println(Math.round(-3.9));//-4
System.out.println(Math.sin(Math.PI/6));//0.4999999999999999
System.out.println(Math.cos(Math.PI/3));//0.5000000000000001
System.out.println(Math.tan(Math.PI/4));//0.9999999999999999
System.out.println(Math.toDegrees(Math.PI/2));//90.0
System.out.println(Math.toRadians(90));//1.5707963267948966
System.out.println(Math.cbrt(8));//2.0
System.out.println(Math.hypot(0 - 1, 0 - 1));//1.4142135623730951
}
}
Scanner类
主要用于负责数据输入的类,底层是和IO流相关。
需要先导包
导包方法: import java.util.Scanner;
输入数据前提方法Scanner xxxx = new Scanner(System.in);
获取方法: 类型 line = input.方法();
方法
- String next():获取直到遇到空格为止的一个字符串
- String nextLine():获取直到遇到回车为止的一个字符串
- int nextInt():获取下一个整数
- byte short long double nextDouble();获取下一个double类型数
- boolean nextBoolean();获取下一个booleat类型数
- float nextFloat();获取下一个float类型数
用法
import java.util.Scanner;
public class Sample {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("输入一句话:");
String line = input.nextLine();
System.out.println(line);
System.out.print("输入三个单词:");
String word1 = input.next();
String word2 = input.next();
String word3 = input.next();
System.out.println(word1);
System.out.println(word2);
System.out.println(word3);
}
}
String类
String是一个类,它描述的是字符串。在Java代码当中,所有字符串常量(字符串字面量)都是 String类的一个实例对象。并且,字符串一旦创建,则不可修改! 不可修改其长度,不可修改其内容 。所 以将来对字符串内容的改变,不能在原地改,只能重新创建一个字符串。
public class Sample {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "ab" + "dc";
//上述代码一共有几个字符串?
//四个"abc" "ab" "dc" "abdc"
}
}
获取相关
- char charAt(int index):获取指定角标index处的字符
- int indexOf(int ch):获取指定字符(编码)在字符串中第一次(从左到右)出现的地方返回的是 角标。如果是-1 表示不存在
- int lastIndexOf(int ch):获取指定字符(编码)在字符串中第一次(从右到做)出现的地方返回的 是角标 int indexOf(String str):获取指定字符串在本字符串中第一次(从左到右)出现的地方返回的是 角标
- int lastIndexOf(String str):获取指定字符串在本字符串中第一次(从右到左)出现的地方返回 的是角标
- int length():获取字符串的长度(字符的个数)
- String[] split(String regex):将字符串按照regex的定义进行切割(regex指的是正则表达式)
- String substring(int beginIndex):截取一段子字符串,从beginIndex开始到结尾
- String substring(int beginIndex, int endIndex):截取一段子字符串,从beginIndex开始到 endIndex(不包含)
判断相关
- int compareTo(String anotherString):按照字典顺序比较两个字符串的大小
- boolean contains(String another):判断当前字符串中是否包含指定字符串
- another boolean equals(String another):比较当前字符串与指定字符串的内容是否相同
- boolean isEmpty():判断当前字符串是否为空,length() == 0
- boolean startsWith(String prefix):判断该字符串是否以prefix开头
- boolean endsWith(String suffix);判断该字符是否以suffix结尾
修改相关
- String toLowerCase():将字符串中所有的英文字母全部变为小写
- String toUpperCase():将字符串中所有的英文字母全部变为大写
- String trim():将字符串中两端的多余空格进行删除
- String replace(char oldCh,char newCh):将字符串中oldCh字符替换成newCh字符
Character类
Character它是char基本数据类型的 包装类 ,有这么几个静态方法我可目前可以使用到的
- static boolean isDigit(char ch):判断字符是否是数字
- static boolean isLetter(char ch):判断字符是否是字母
- static boolean isLetterOrDigit(char ch):判断字符是否是数字或字母
- static boolean isLowerCase(char ch):判断是否是小写字母
- static boolean isUpperCase(char ch):判断是否是大写字母
- static boolean isSpaceChar(char ch):判断是否空白字母(空格 制表符 回车)
第五章 函数
函数的概念
函数的定义就是指一段具有独立功能的代码,减少代码冗余,提高程序的利用率和效率。
如何去定义函数
- 需要一个封闭的空间,将这段独立性的代码进行封装,用一对大括号
- 需要对每一个封闭的空间进行命名,函数名
- 函数所需要的一些原始数据
- 函数所产生的一些结果数据
函数的语法格式
修饰符 函数类型 返回值类型 函数名(数据类型 数据1,数据2,数据3){
独立功能的代码片段;
return 函数的结果;
}
- 修饰符 :指的是函数的访问权限,public private 默认 protected
- 函数类型:函数的分类,本地函数native,静态函数 static ,同步函数synchronized
- 返回值类型:指的就是函数计算结果的数据类型 如果函数没有返回值 则为void
- 函数名:就是函数的名称
- 参数列表:指的是外界向函数传入的数据(实际参数),由这些参数变量进行接收(形式参 数)
- 函数体:具有独立功能的代码片段;
- return:仅仅表示函数结束!如果函数有返回值,则return后跟返回值;如果没有返回值,则 return可以不写,但是是存在的(隐藏的 在最后一行)
根据形参和返回值来看,函数有如下几个分类
- 有参数有返回值
求三个数字当中的最大值
public class Sample {
public static void main(String[] args) {
int max = getMax(1,2,3);
System.out.println(max);
}
public static int getMax (int a , int b , int c) {
/*
if (a >= b && a >= c) {
return a;
}else if (b >= a && b >= c) {
return b;
}else {
return c;
}
*/
if (a >= b && a >= c) {
return a;
}
if (b >= a && b >= c) {
return b;
}
if (c >= a && c >= b) {
return c;
}
return -10000;
}
-
有参数无返回值
-
无参数有返回值
获取当前时间的字符串
public class Sample {
public static void main(String[] args) {
String currentTime = getTime();
System.out.println(currentTime);
}
public static String getTime() {
//1.获取总毫秒数
long millis = System.currentTimeMillis();
//2.计算总秒数
long seconds = millis / 1000;
//3.计算总分钟数
long minutes = seconds / 60;
//4.计算总小时数
long hours = minutes / 60;
//5.计算当前小时数
long currentHours = hours % 24;
//6.计算当前分钟数
long currenrMinutes = minutes % 60;
//7.计算当前秒数
long currentSeconds = seconds % 60;
return currentHours + ":" + currenrMinutes + ":" +currentSeconds;
}
}
- 无参数无返回值
其实就是在函数中直接输出想要获取的信息
函数的运行原理
函数的运行是基于栈运行的
栈:是一种先进后出的容器,我们这里面所说的栈是指JVM中的栈内存空间
每一个函数,叫做栈帧,栈帧中所包含的内容有函数的定义,参数列表,函数的执行内容代码
每一个函数要运行,就相当于这个栈帧进入到栈内存中-入栈
如果一个函数即将结束,将这个栈帧从栈顶移出-出栈
如果栈内存中有多个栈帧,运行的是最上面的栈帧,底下的栈帧暂停运行,直到该栈帧为栈顶元素
比如:主函数先进栈,开始逐行运行,如果执行到第n行,调用另外一个函数A,则主函数在第n行 暂停运行,将另一个函数A的栈帧入栈,再继续逐行运行,直到函数A的内容执行完毕,函数A出栈,主 函数接着从第n行继续向下执行。以此类推。
函数重载
同一个类中可以出现多个同名函数,这个现象就叫做函数的重载(overload)
如何区分是否重载
- 前提必须是同名
- 返回值类型无关(返回值类型只和函 数的计算功能相关)
- 和权限也没有关系
- 和形式参数的名称也无关
- 只和形式参数的数据类型有关 (数量,排列组合)
public static void show(int a ,float b ,char c){}
下列哪些是该函数的重载:
- int show(int x, float y, char z) :不算重载 数据类型都是int float char
- void show(float b,int a,char c):算重载,顺序不一样float int char
- void show(int a,int b,int c):算重载,顺序不一样int int int
- double show():算重载,参数不一样
寻找重载的流程
- 看是否有确切的参数定义匹配,int int 找 int int
- 看是否有可兼容的参数定义匹配,int int找double double或int double或double int
- 如果可兼容的参数定义匹配较多,会报引用确定报错 引用不明确
即 如果 int int既可以找 double int也可以找int double 引用不明确会报错
函数的递归
定义
函数的递归就是指函数自身调用自身。
相对而言,从内存的角度而言,函数如果过多的自我调用,势必会对内存不友好,占用过多
通常来讲,同样的问题用递归写要比用迭代写代码量较少
写递归时,一定要先确定递归结束条件-递归边界
案例
递归实现斐波那契数列
public class Sample {
public static void main(String[] args) {
/*
1 1 2 3 5 8 13 21 34 55 ...
1 x=1,x=2
f(x) =
f(x-1) + f(x-2) x>2
f(5)
f(4) f(3)
f(3) f(2) f(2) f(1)
f(2) f(1)
*/
//递归O(2^n)
System.out.println(f(35));
//迭代O(n)
System.out.println(fibo_it(35));
}
public static int fibo_it(int x) {
if (x == 1 || x == 2) {
return 1;
}
/*
1 1 2 3
c
a b
*/
int a = 1;
int b = 1;
int c = 0;
for (int i = 3; i <= x; i++) {
c = a + b;
a = b;
b = c;
}
return c;
public static int f(int x) {
if (x == 1 || x == 2) {
return 1;
}else {
return f(x-1) + f(x-2);
}
}
}
汉诺塔问题
public class Demo81 {
/*
前4个 x->z
前3个 x->y
前2个 x->z
前1个 x->y
第2个 x->z
前1个 y->z
第3个 x->y
前2个 z->y
前1个 z->x
第2个 z->y
前1个 x->y
第4个 x->z
前3个 y->z
前2个 y->x
前1个 y->z
第2个 y->x
前1个 z->x
第3个 y->z
前2个 x->z
前1个 x->y
第2个 x->z
前1个 y->z
*/
public static void main(String[] args) {
String x = "x";
String y = "y";
String z = "z";
hano(3,x,y,z);
//前3层从 x->z
//前2层从 x->y
}
public static void hano(int level,String begin,String mid,String end) {
if (level == 1) {
System.out.println(begin+"->"+end);
} else {
//前level-1层
hano(level - 1,begin,end,mid);
System.out.println(begin+"->"+end);
//前leve1-1层
hano(level - 1,mid,begin,end);
}
}
}
第六章 数组
数组的概念及定义
数组概念
数组主要用于解决大量数据计算和存储的问题
比如:输入100个数字,统计其中的最大值和最小值并计算平均值,创建100个变量,会有一堆if else语句,比较麻烦。
数组是Java提供的一种最简单的数据结构,可以用来存储一个元素 个数固定 且 类型相同 的有序 集。
数组在内存中的情况
栈:主要用于运行函数的内存
堆:主要用于存储数据对象的内存
每一个数组而言,都是存在堆内存当中,每一个数组都是一个对象
注意
数组本质上就是在堆内存中一系列地址连续且空间大小相等的存储空间(变量),每一个存 储空间用来存储数据(基本,引用)
数组是在堆内存中存储,称之为是一个对数对象,并且在堆内存中存储的数据都有 默认初始 化 的流程。所以数组创建之初,每一个存储空间里面都会被JVM初始化该数据类型对应的零值。
数组的地址是连续的,所以通过公式:An=A1+(n-1)*d可以快速访问到其他的元素,所以对于 数组而言查找元素比较快的。将元素的真实物理地址转换成对应的角标获取元素。
如何来调用数组呢?
通过一个变量存储该数组在堆内存当中的首元素的地址。 当数组一旦定义出来,其长度不可变,存储空间的内容是可变的 所以我们在定义数组的时候,要么把长度固定,要么直接输入相关的元素。
数组定义
一维数组的定义
定义
//创建一个指定长度且指定数据类型的一维数组,名称为数组名,虽然没有指定元素,但是会有默认值
数据类型[] 数组名 = new 数据类型[长度];
//创建一个指定元素且指定数据类型的一维数组,名称为数组名,虽然有指定元素,还是有默认初始化这个步骤的!
数据类型[] 数组名 = new 数据类型[]{数据1,数据2,...,数据n};
数据类型[] 数组名 = {数据1,数据2,...,数据n};
方法
arr.length 一维数组的长度
二维数组的定义
定义
二维数组,在表现形式上就是一个表格,在操作表格的时候以行列来操作
0 | 1 | |
---|---|---|
0 | 0.0 | 0.1 |
1 | 1.0 | 1.1 |
2 | 2.0 | 2.1 |
所谓的二维数组,本质上就是一个一维数组,只不过该一维数组里面的元素是另一个一维数组而已
public class Sample {
public static void main(String[] args) {
//数据类型[][] 矩阵名 = new 数据类型[row][col];
int[][] matrix = new int[3][2];
/*
数据类型[][] 矩阵名 = new 数据类型[][] {
{...},
{...},
{...}
};
数据类型[][] 矩阵名 = {
{...},
{...},
{...}
};
*/
int[][] matrix2 = {
{1,2,3},
{4,5,6},
{7,8,9}
};
for (int i = 0; i < matrix2.length; i++) {
for (int j = 0; j < matrix2[i].length; j++) {
System.out.print(matrix2[i][j] + " ");
}
System.out.println();
}
int[][] matrix3 = {
{1},
{1,2,3},
{1,2,3,4},
{7,6,5,4,3,2,1}
};
for (int i = 0; i < matrix3.length; i++) {
for (int j = 0; j < matrix3[i].length; j++) {
System.out.print(matrix3[i][j] + " ");
}
System.out.println();
}}}
方法
arr.length 二维数组的行数
arr.[0]表示另一个一维数组
arr[0].length 第一个一维数组的长度
常用数组操作
数组遍历问题
public class Sample {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5,6,7,8,9};
//String str str.length()-函数
//int[] arr arr.length-属性
for (int i = 0; i < arr.length; i++) {
arr[i] = arr[i] * 10;
System.out.println(arr[i]);
}
//通过角标遍历 可以在遍历的过程中对指定的元素进行修改
//foreach遍历 主要针对的是一些可迭代对象 Iterable
/*
for (数据类型 变量名 : 可迭代容器) {
}
*/
for (int num : arr) {
//num -> arr[i]
num = num / 10;
System.out.println(num);
}
//这种遍历方式 只能获取元素,不能修改元素
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
数组最值问题
public class Sample {
public static void main(String[] args) {
int[] arr = new int[]{3,6,8,2,9,4,5,1,7};
int min = arr[0];
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
if (arr[i] > max) {
max = arr[i];
}
}
System.out.println(max);
System.out.println(min);
}
}
数组扩容问题
public class Sample {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
arr = add(arr,6);
arr = add(arr,6);
arr = add(arr,6);
arr = add(arr,6);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}//123456666
//在指定的数组arr中添加元素element
public static int[] add(int[] arr, int element) {
int[] newArr = new int[arr.length + 1];
for (int i = 0; i < arr.length; i++) {
newArr[i] = arr[i];
}
newArr[newArr.length - 1] = element;
return newArr;
}
}
数组排序问题
选择排序算法
从小到大正方向获取
public class Sample {
//选择排序
public static void main(String[] args) {
int[] arr = {8,9,2,6,7,1,4,5,3};
for (int i = 0; i < arr.length - 1; i++) { //-1 n个数字没有第n轮
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
swap(arr,i,j);
}
}
}
print(arr);
}
//[1, 2, 3, 4, 5]
public static void print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length;i++) {
System.out.print(arr[i]);
if (i == arr.length - 1) {
System.out.println("]");
} else {
System.out.print(", ");
}
}
}
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
冒泡排序算法
从大到小反方向获取
public class Sample {
//冒泡排序
public static void main(String[] args) {
int[] arr = {8,9,2,6,7,1,4,5,3};
for (int i = 0; i <arr.length - 1; i++) {//-1 表示n个数字只有n-1轮
for (int j = 0; j < arr.length - 1 - i; j++) {//-1 避免重复比较(当前最大和上一
轮最大)
if (arr[j] > arr[j + 1]) {
swap(arr,j,j+1);
}
}
}
print(arr);
}
public static void print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length;i++) {
System.out.print(arr[i]);
if (i == arr.length - 1) {
System.out.println("]");
} else {
System.out.print(", ");
}
}
}
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
插入排序算法
从前到后逐个排序
public class Sample {
//插入排序
public static void main(String[] args) {
int[] arr = {8,9,2,6,7,1,4,5,3};
for (int i = 1; i < arr.length; i++) {
int e = arr[i];
int j = 0;
for (j = i; j > 0 && arr[j - 1] > e; j--) {
arr[j] = arr[j - 1];
}
arr[j] = e;
}
print(arr);
}
public static void print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length;i++) {
System.out.print(arr[i]);
if (i == arr.length - 1) {
System.out.println("]");
} else {
System.out.print(", ");
}
}
}
}
计数排序算法
创建最大减去最小个空间 然后输入个数
public class Sample {
//计数排序
public static void main(String[] args) {
int[] arr = {-2,9,-1,12,8,-3,6,7,4,5,2,1,0,8,6,7,4,-3,-2,-1,-1,7};
int min = arr[0];
int max = arr[0];
//O(n)
for (int i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
if (arr[i] > max) {
max = arr[i];
}
}
int[] temp = new int[max - min + 1];
//对应关系 index = number - min number = index + min
//O(n)
for (int i = 0; i < arr.length; i++) {
temp[arr[i] - min]++;
}
//temp[index] 表示index对应的数字number出现的次数
int k = 0;
//O(n)
for (int index = 0; index < temp.length; index++) {
while (temp[index] != 0) {
arr[k] = index + min;
k++;
temp[index]--;
}
}
print(arr);
}
public static void print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length;i++) {
System.out.print(arr[i]);
if (i == arr.length - 1) {
System.out.println("]");
} else {
System.out.print(", ");
}
}
}
}
基数排序算法
个十百千位从小到大排序
import java.util.LinkedList;
public class Sample {
//基数排序
public static void main(String[] args) {
int[] arr = {102,203,321,13,12,78,96,34,37,28,6,8,5,6};
//1.先找到最大值 决定轮数
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
int radex = (max + "").length();
//2.创建十个桶 每一个桶是LinkedList
LinkedList<Integer>[] queues = new LinkedList[10];
for (int i = 0; i < queues.length; i++) {
queues[i] = new LinkedList<Integer>();
}
//3.进行数字分类和规整
//r=0个位 r=1十位 r=2百位...
for (int r = 0; r < radex; r++) {
//先按照r进行分类
for (int i = 0; i < arr.length; i++) {
int index = getIndex(arr[i],r);//获取数字的r位 返回该数字要去的桶的角标0~9
queues[index].offer(arr[i]);
}
//然后在重新规整到arr里
int k = 0;
for (int index = 0; index < queues.length; index++) {
while(!queues[index].isEmpty()) {
arr[k++] = queues[index].poll();
}
}
}
print(arr);
}
public static int getIndex(int number, int r) {
//123 r=0
//123 r=1
//123 r=2
int index = 0;
for (int i = 0; i <= r; i++) {
index = number % 10;
number /= 10;
}
return index;
}
public static void print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length;i++) {
System.out.print(arr[i]);
if (i == arr.length - 1) {
System.out.println("]");
} else {
System.out.print(", ");
}
}
}
}
二分查找算法
有一个前提,所查找的数据集必须是有序的(升序,降序)
public class Sample {
//二分查找
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9};
int min = 0;
int max = arr.length - 1;
int mid = (min + max) / 2;
int key = 10;
while (arr[mid] != key) {
if (key < arr[mid]) {
max = mid - 1;
}
if (arr[mid] < key) {
min = mid + 1;
}
if (min > max) {
mid = -1;
break;
}
mid = (min + max) / 2;
}
System.out.println(mid);
}
}
可变长参数列表
进入函数的时候创建一维数组
public class Sample {
public static void main(String[] args) {
show(1);
show(1,2,3);
show("hehe","lala","haha","xixi","heihei");
}
public static void show(int ... nums) {
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
System.out.println();
}
public static void show(String ... strs) {
for (int i = 0; i < strs.length; i++) {
System.out.print(strs[i] + " ");
}
System.out.println();
}
}