JavaSE总结
2021/1/12
静态编译语言:C C++ Java
- 静态:在定义变量的时候有明确的数据类型的区分
- 编译:将源代码全部进行编译 生成一个可执行的二进制文件 计算机去执行这个二进
制文件来运行程序。(翻译一本英文书)
动态解释语言:Python JS
- 动态:在定义变量的时候没有明确的数据类型的区分
- 解释:将源代码从头到尾 读取一行 编译一行 运行一行(同声传译)
软件开发
软件开发的定义就是去编写上述软件,软件开发的流程是什么?
- 需求分析
- 编码实现
- 测试编码
- 上线运维
- 更新迭代
- 下线
Java最大的特点——跨平台
- 跨平台的意思就是说,一个软件可以在多个平台上运行,而不用更改软件的内容。
Java源代码文件后缀名为xxx.java 所编译出来的二进制文件后缀名为xxx.class(字节码)
j
jdk安装目录介绍
- bin目录:binary放的都是开发工具
- javac.exe:java编译工具
- 用法: javac java.exe:java运行工具
- 用法: java [-options] class [args…] (执行类) 或 java [-options] -jar jarfile [args…] (执行 jar 文件) db目录:放的是支持数据库开发的一些工具包
- include目录:放的是一些链接底层的一些C头文件代码
- jre目录:jdk自带的运行环境
- lib目录:library 存放的是一些第三方Java库 javafx-src.zip:javafx图形化界面开发的源码包
- src.zip:Java本身的源代码包
用vscode打开一个java文件报错:
test.java is a non-project file, only syntax errors are reported.
其实是打开方式不对。正确的java文件打开方式应为先打开文件夹,再打开文件,这样就不会报错。
2021/1/13
标识符命名的规范:
- 大驼峰式:主要针对类名,接口名。所有单词的首字母大写
- 小驼峰是:主要针对于变量名,函数名。除了第一个单词之外,其他单词首字母大写
- 常量规范:所有单词字母大写,单词与单词之间用下划线分隔
- 包名规范:所有单词字母小写,单词与单词之间用句号 . 分隔
文档注释 /** 注释内容 内部可以进行换行 */ :文档注释可以被编译器识别,并生成相应
的程序说明书。对某一个类进行文档生成时,该类必须是public型
数据类型
- 整型
- byte:1个字节
- short 2字节
- long 8字节
- int 4个字节
- 浮点型
- float 4个字节
- double 8个字节
- 字符型
- char 2字节
- 布尔型
- boolean 不确定
在常量中,整型常量默认int类型,小数常量默认是double类型
布尔类型,如果是单一变量的话,在JVM中true被认为是1 false被认为是0 所以是4字节存
如果是布尔类型数组的话,在JVM中true和false被认为是byte类型 1字节
算数运算符
a++
++a
public class Sample
{ public static void main(String[] args) {
/*a++
1.先开辟临时存储区 将a的值赋值进去
2.a自身加一
3.临时存储区的值等待被调用 输出 赋值 参与运算 */
int i = 0;
i++; System.out.println(i++);
System.out.println(i);
int j = i++; System.out.println(i);
System.out.println(j);
i = i++; System.out.println(i);
i = i++; System.out.println(i);
int a = 1; System.out.println(a++ + ++a + a++ + a++ + ++a);
} }
获取从键盘输入的值
Scanner scanner1 = new Scanner(System.in);
当**"Resource leak: ‘scanner’ is never closed"警告**
在Scanner语句出现解决办法
需要在main方法最后加一个 scanner.close();
2021/1/14
Switch分支语句
与分支语句一样,都是对条件的的判断,switch一般用在条件比较多的情况下啊,但有个重要 细节,,if语句可以对区间值去进行判断,switch只能对固定值进行判断
当变量匹配的相关case的值的时候,执行case中的语句,直到遇到break结束;如果该case语句
中没有break,则继续向下执行,直到遇到另外一个break结束
for循环语句
主要解决具有规律的问题
常见的循环问题
- 已知循环次数用for
- 未知循环次数和已知循环条件一般用while
break:终止break最近的一层循环
continue:跳过本次循环开启下一次的循环
例题知识点
- 产生一个随机数
Math.random();产生一个[0,1)的小数
如果要产生一个[a,b]之间的整数 [0,1) * 10 = [0,10) + 3 = [0,13) [0,1) * (b - a + 1) + a - 获取百位 :num%10;
- 获取各位 :num/100;
- 回文 :从前和向后都是一样的数字
- 反转数据 :
- 123456 % 10 = 6 renum * 10 + 6 = 6
- 12345 % 10 = 5 renum * 10 + 5 = 65
- 1234 % 10 = 4 renum * 10 + 4 = 654
- Math.pow(底数,次方)
- Math.sqrt()平方根
素数的个数
public class Demo44 { //25 2 3 4 5 6 7 8 9 ~ 24 // i //7 2 3 4 5 6 // i public static void main(String[] args) {
int count = 0;//素数的个数
for (int number = 2; number <= 1000; number++) {
boolean flag = true; //默认是素数
for (int i = 2; i <= number / 2; i++) {
if (number % i == 0) {
flag = false;
break; } }
if (flag) {
System.out.print(number + "\t");
count++;
if (count % 8 == 0) {
System.out.println();
}
}
}
}
}
2021/1/16
例题知识点
Demo30
(几何:两个圆)编写程序,提示用户输人两个圆的中心坐标和各自的半径值,然后决定第二个圆是在第一个圆内,还是和第一个圆重叠,如图3-10所示。
- 思路:先算两个圆心距的大小,| r1-r2|>=圆心距,就再圆内;|r1+r2|>=圆心距,就在圆上;|r1+r2|<圆进距,就圆外
import java.util.Scanner; public class Demo30 { public static void main(String[] args) {
//数据:两个圆的圆心坐标 半径 圆心距
//1.提示用户输入两个圆的圆心坐标和半径
Scanner input = new Scanner(System.in);
System.out.print("请输入圆1的坐标以及半径:");
double ox1 = input.nextDouble();
double oy1 = input.nextDouble();
double r1 = input.nextDouble();
System.out.print("请输入圆2的坐标以及半径:");
double ox2 = input.nextDouble();
double oy2 = input.nextDouble();
double r2 = input.nextDouble();
//2.计算两个圆的圆心距
double distance = Math.sqrt(Math.pow(ox1 - ox2,2) + Math.pow(oy1 - oy2,2));
//3.判断圆心距和两个半径的关系
//distance <= r1 - r2 圆2在圆1内
//distance < r1 + r2 圆2与圆1相交
//distance >= r1 + r2 圆2在圆1外
if (distance <= r1 - r2) {
System.out.println("圆2在圆1内");
}
else if (distance < r1 + r2) {
System.out.println("圆2与圆1相交");
} else{
System.out.println("圆2在圆1外"); } } }
Demo33
两个整数4和2的最大公约数是2。两个整数16和24的最大公约数是8。如何编写程序来求最大公约数呢?
- 公约数:两个数共同的最大除数;首先两个数,判断大小,只需要将小的值取出来,要找最大的,就从大往小循环,当,两个数取余都为0 是,就结束循环
import java.util.Scanner; public class Demo33 {
public static void main(String[] args)
{ /*24 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ~ 24 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 i 7 1 2 3 4 5 6 7 11 1 2 3 4 5 6 7 8 9 10 11 i */
//1.输入两个数字并判断大小
Scanner input = new Scanner(System.in);
System.out.print("请输入两个数字:");
int num1 = input.nextInt(); int num2 = input.nextInt();
int min = num1 < num2 ? num1 : num2;
//2.从min开始向1循环递减,如果找到一个数字i能够把num1和num2同时整除
//那么i就是最大公约数gcd
int gcd = 1;
for (int i = min; i > 0; i--)
{
if (num1 % i == 0 && num2 % i == 0) {
gcd = i; break;
}
}
System.out.println("最大公约数为:" + gcd); }
}
Demo35
要解决的问题是,编写一个程序,提示用户输人一个字符串,然后给出该字符串是否是回文。
- 先输入一个字符串,所谓回文,就是从前往后和从后往前数都是一样的,相当于,第一个和最后一个一样,第二个和倒数第二个一样,一次类退,直到中间结束
- charAt(index ):获取index处对应的字符
import java.util.Scanner;
public class Demo35 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入一段话:");
String str = input.nextLine();
int l = 0;
int r = str.length() - 1;
boolean flag = true;
while (l < r) {
if (str.charAt(l) == str.charAt(r)) {
l++;
r--;
}
else {
flag = false;
break; } }
if (flag) {
System.out.println(str + " 这句文本是回文"); }
else { System.out.println(str + " 这句文本不是回文");
}
}
}
Demo36
现在的问题是在5行中显示前50个素数,每行包含10个数。该问题可分解成以下任务:·
判断一个给定数是否是素数。
针对number=2,3,4,5,6,…,测试它是否为素数。
统计素数的个数。
打印每个素数,每行打印10个。
- 素数:只能被本身和一整除;先写个while(小于50)再写个boolean变量来判别是否为素数,再用个循环,判断能整除的数,能整除就不是素数
public class Demo36 {
public static void main(String[] args) {
int count = 0;
int number = 2;
while (count < 50) {
boolean flag = true;
for (int i = 2; i <= number / 2; i++) {
if (number % i == 0) {
flag = false; break;
}
}
if (flag) {
System.out.print(number + "\t");
count++; if (count % 10 == 0) {
System.out.println();
}
}number++;
}
}
}
Demo41
- 我的思路:先用一个循环表示是行,再嵌套三个,一个表示空格,第二个表示左边一般,最后一个表示右边
- 老师思路:因为每行两边的数都是一样的,所以可以利用坐标轴,就可以利用绝对值取计算
public class Demo41 { public static void main(String[] args) {
/*
第4行 4 3 2 1 2 3 4 3 2 1 0 1 2 3 y = |x| + 1 x∈[-3,3]
第5行 5 4 3 2 1 2 3 4 5 4 3 2 1 0 1 2 3 4 y = |x| + 1 x∈[-4,4]
第i行 y = |x| + 1 x∈[-(i-1),i-1] */
for (int i = 1; i <= 7; i++)
{
for (int k = 1; k <= 7 - i ;k++)
{
System.out.print(" ");
}
for (int j = -(i - 1); j <= i - 1; j++)
{ System.out.print(Math.abs(j) + 1 + " ");
}
System.out.println();
}
}
}
Demo47
- 阶乘可以定义一个变量,然后循环,让这个变量乘于循环的值,再等于这个变量
public class Demo47 { public static void main(String[] args)
{ double e = 1; int max = 10; long item = 1;
for (int i = 1; i <= max; i++) { item = item * i;
//1 2*1 3*2*1
e = e + 1.0 / item;
//1/1! 1/2! 1/3!
}
ystem.out.println(e); } }
Demo50
(十进制到二进制)编写程序,提示用户输入一个十进制整数,然后显示对应的二进制值。在这个程序中不要使用Java的Interger.toBinaryString(int)方法。
- 思路:先输入一个十进制数,再循环,将整数取余+一个空字符串,在除2,字符串的加,就是连接
import java.util.Scanner;
public class Demo50 {
public static void main(String[] args) {
//1.输入一个数字
Scanner input = new Scanner(System.in);
System.out.print("请输入一个十进制整数:");
int number = input.nextInt();
/*13 / 2 = 6 ~ 1 6 / 2 = 3 ~ 0 3 / 2 = 1 ~ 1 1 / 2 = 0 ~ 1 "" + 1 = "1" 0+"1"="01"
1+"01"="101"
1+"101"="1101" */
String binStr = "";
while (number != 0)
{ binStr = number % 2 + binStr;
number /= 2; }System.out.println(binStr); } }
Demo48
(完全数)如果一个正整数等于除它本身之外其他所有除数之和,就称之为完全数。例如:6是第一个完全数,因为6=1+2+3。下一个完全数是28=14+7+4+2+1。10 000以下的完全数有四个。编写程序,找出这四个完全数。
- 思路:先外层循环,再内层循环,算出所有除数,再将所有的除数加起来(可以定义一个变量,这个变量加上内层循环的值,等于这个标量),然后,在内层循环外,判断一个外层循环的值是否等于这个变量
public class Demo48 {
public static void main(String[] args) {
for (int i = 1; i <= 10000; i++) {
int sum = 0;
for (int j = 1; j < i; j++) {
if (i % j == 0) {
sum = sum + j;
}
}
if (sum == i)
System.out.print(i + "\t");
}
}
}
2021/1/17
Math类
用于数学计算的一个工具类
常量
- static double E :自然对数
- static double PI:圆周率
取整方法
- ceil :向上取整
- floor:向下取整
- round:四舍五入
指数
- 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 hyppot(double deltX,double deltY):返回两点之间的距离
- static double random():返回一个[0,)之间的随机小数
##Scanner类
主要负责获取从输入的类
- String next():获取知道遇到空格结束
- String nextline();获取知道遇到回车的一个字符串
Random类
主要获取随机数的类
- boolean nextBoolean():随机产生布尔类型的值
- double nextdouble():随机生成0.0~1.0之间的小数
- double nextint():随机产生~的次方幂的整数
- double nextint(n):随机产生一个[0,n)的整数
import java.util.Random; public class Sample {
public static void main(String[] args) {
Random random = new Random();
for (int i = 1; i <= 10; i++) { System.out.print(random.nextBoolean() + " "); }System.out.println();
for (int i = 1; i <= 10; i++) { System.out.print(random.nextInt(2) + " "); }System.out.println();
for (int i = 1; i <= 10; i++) { System.out.print(random.nextInt() + " "); }System.out.println(); } }
String类
string 是一个类,它代表的十字符串;字符串一旦创建,就不可修改( 长度和内容都不能修改)
获取相关
- 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的定义进行切割
- String substring(int beginIndex):截取一段字符串,从beginIndex开始到结尾
- String substring(int beginIndex,int endIndex):截取一段字符串,从开始角标到结束角标(结束角标的值不包括)
判断相关
- int compareTo(String anotherString):按照字典顺序比较两个字符串的大小
- boolean contains(String another):判断当前字符串中是否包含指定字符串another
- boolean equals(String another):判断当前字符串与指定字符串的内容是否相同
- boolean isEmpty():判断当前字符串是否为空,length()==0
- boolean startsWith(String preffix):判断字符串是否以prefix开头
- boolean endsWith(String suffix):判断字符串是否已suffix结尾
修改相关
- String toLowerCase():将字符串中所有英文字母全部变成小写
- String toUpperCase():将字符串所有英文字母全部变成大写
- String trim();将字符串中两端的多余的空格进行删除
- String replace(char oldCh,char newCh):将字符串oldCh字符替换成newCh字符
例题
如何删除字符串中左右两端出现的空格,不用trim
- 思路:先将左边坐标定义为0,将右边定义为 字符串的长度减一;循环当前角标的值是否为空格,是就加一,不是就结束循环;同理从右边开始,最后截取前面角标到后面角标的值,就是去除左右两边空格的字符串
public class Sample {
public static void main(String[] args) {
String str = " 123123123 12123 ";
//去空格后"123123123 12123" int l = 0;
int r = str.length() - 1;
while (str.charAt(l) == ' ') {
l++;
}
while (str.charAt(r) == ' ')
{
r--;
}
System.out.println("[" + str.substring(l,r + 1) + "]");
}
在字符串"abcbcbcbcbcbc"中统计"bcb"出现的次数
- 非贪心算法:先获取s2在s1中第一次出现的角标,如果没有就退出循环,没退出。次数就加一次,再将剩下的字符串截取下来,从,第一次出现的角标加上s2的长度
非贪心算法 3个
String temp = s1;
int count = 0;
while (true) {
int index = temp.indexOf(s2);
if (index == -1)
{
break;
}
count++; ,
temp = temp.substring(index + s2
.length());
}
System.out.println(count);
- 贪心算法:先将判断要循环的次数,s1的,长度减去s2的长度,再循环,当s1某角标的值等于s2的第一个值,再判断s1截取下的字符串(当前角标到当前角标加s2的长度)等于s2的值相等,就加一次次数
public class Sample {
public static void main(String[] args)
{ //最好的算法KMP算法
String s1 = "abcbcbcbcbcbc";
String s2 = "bcb"; //贪心算法 5个
int count = 0;
for (int i = 0; i < s1.length() - s2.length() + 1; i++) {
if (s1.charAt(i) == s2.charAt(0)) {
if (s2.equals(s1.substring(i,i + s2.length())))
{ count++; } } }System.out.println(count);
查找两个字符串中最长的公共子串
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210117204543740.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3F1YW54aW5xaW5n,size_16,color_FFFFFF,t_70#pic_center
blic class Sample { public static void main(String[] args) { String s1 = "c is a program but is diffcult"; String s2 = "Java is a program but is slow";
for (int len = s2.length(); len > 0; len--) {
for (int l = 0,r = len - 1; r < s2.length(); l++,r++) { String temp = s2.substring(l,r + 1); if (s1.contains(temp)) { System.out.println(temp); return;//直接结束程序 } } } } }
2021/1/18
Character类
character他是char基本数据类型的包装类
- isDigit(char ch):判断字符是否是数字
- isLetter(char ch):判断字符是否是字母
- isLetterOrDigit(char ch):判断字符是否是数字或字母
- isLowerCase(char ch):判断是否是小写字母
- isUpperCase(char ch):判断是否是大写写字母
- static boolean isSpaceChar(char ch):判断是否空白字母(空格 制表符 回车)
例题分析
Demo59:(十进制转十六进制)编写一个程序,提示用户输入0~~15之间的一个整数,显示其对应的十六进制数。下面是一个运行示例:
- 思路:先循环,再取余,当余数小于10就输出,如果大于十小于等于15 就将余数加55;最后这个数除以16
import java.util.Scanner;
public class Demo59 {
public static void main(String[] args) {
//十进制转十六进制
Scanner input = new Scanner(System.in); System.out.print("Enter a number:");
int number = input.nextInt();
String hex = "";
while (number != 0) {
int y = number % 16;
if (y < 10) {
hex = y + hex;
} else {
hex = (char)(y + 55) + hex;
}
number /= 16;
}
System.out.println(hex); } }
Demo60:检测子串)编写一个程序,提示用户输人两个字符串,检测第二个字符串是否是第一个字符串的子串。
- 思路:先循环找出第一个字符串的字符是否等于第二个字符串的第一个字符,再循环第二个的后面的字符与第一个字符串匹配
public class Demo60 {
public static void main(String[] args) {
String s1 = "My name is Hello";
String s2 = "Heit"; /*My name is Helloi j nanak */
for (int i = 0; i < s1.length(); i++) {
if (s1.charAt(i) == s2.charAt(0)) {
boolean flag = true;
for (int k = 1,j = i + 1; k < s2.length();k++,j++) {
if (s2.charAt(k) != s1.charAt(j)) {
flag = false; break;
}
}if (flag) {
System.out.println("true"); return; } } }
System.out.println("false"); } }
Demo61:(检查SSN)编写一个程序,提示用户输入一个社保号码,它的格式是DDD-DD-DDDD,其中D是一个数字。你的程序应该判断输入是否合法。
- 我的思路:判断第3个字符和第6个字符是否等于’ - ',是就是合法,不是就是不合法
- 老师思路:先判断3个6 角标的值是否等于’ - ',如果不等于就不合法,再判断==的时,角标是否为数字
import java.util.Scanner;
public class Demo61 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); System.out.print("Enter a SSN:");
String ssn = input.nextLine();
if (ssn.length() != 11) { System.out.println("invalid"); return; }
for (int i = 0; i < ssn.length(); i++) {
if (i == 3 || i == 6) {
if (ssn.charAt(i) != '-') {
System.out.println("invalid");
return; } } else {
if (!Character.isDigit(ssn.charAt(i))) { System.out.println("invalid");
return; } } }
System.out.println("valid"); } }
2021/1/20
函数
什么是函数
函数的定义是指一段独立功能的代码
语法格式
修饰符 函数类型 返回值类型 函数名(数据类型 数据1,数据类型 数据2,...) {
独立功能的代码片段;
return 函数的计算结果;
}
-
函数的访问权限
- public :对所有类可见。使用对象:类、接口、变量、方法
- protected: 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
- default: 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
- private:在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
-
函数类型:本地函数native,静态函数static,同步函数 synchronized
-
返回值类型:就是计算结果需要的数据类型,void没有返回时
-
函数名:函数的名字
-
参数列表:指的是外界向函数传入的数据(实际参数),由这些参数变量进行接收(形式参
数) -
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; }
} }
计算一个数字a的吧次幂
public class Sample {
public static double pow (double a , int b) {
if (a == 0) {
return 0; }
if (b == 0) {
return 1;
}
double result = 1.0;
for (int i = 0; i < Math.abs(b) ; i++) {
result *= a; }
return b > 0 ? result : 1 / result; }
public static void main(String[] args) { System.out.println(pow(2,2));
System.out.println(pow(2,-3)); } }
- 有参数值没返回值
将三个字符串的反转,并拼接打印
public class Sample {
public static void main(String[] args) { print("123","456","789"); }//123 456 789 =? 321654987
public static void print(String s1 , String s2 , String s3) { System.out.println(reverse(s1) + reverse(s2) + reverse(s3)); }
public static String reverse(String s) {
String res = "";
for (int i = s.length() - 1; i >= 0; i--) {
res += s.charAt(i); }
return res; }
函数的运行原理
函数的运行是基于栈运行的
栈:是一种先进后出的容器,我们这里面所说的栈是指JVM中的栈内存空间
每一个函数,叫做栈帧,栈帧中所包含的内容有函数的定义,参数列表,函数的执行内容代码
每一个函数要运行,就相当于这个栈帧进入到栈内存中-入栈
如果一个函数即将结束,将这个栈帧从栈顶移出-出栈
如果栈内存中有多个栈帧,运行的是最上面的栈帧,底下的栈帧暂停运行,直到该栈帧为栈顶元素
比如:主函数先进栈,开始逐行运行,如果执行到第n行,调用另外一个函数A,则主函数在第n行
暂停运行,将另一个函数A的栈帧入栈,再继续逐行运行,直到函数A的内容执行完毕,函数A出栈,主
函数接着从第n行继续向下执行。以此类推
函数的重载
同一个类中可以出现多个同名函数,这个现象就叫做函数的重载(overload)
如何来区分同名函数是否是重载关系呢?前提必须是同名,和返回值类型无关
返回值类型只和函数的计算功能相关),和权限也没有关系,和形式参数的名称也无关!只和形式参数的数据类型有关
(数量,排列组合)
public static void show(int a ,float b ,char c){}
函数的递归
函数的递归就是指函数自身调用自身
- 但凡迭代能够解决的问题,递归都可以解决;递归能够解决的问题,迭代就不一定了
- 相对而言,从内存的角度而言,函数如果过多的自我调用,势必会对内存不友好,占用过多
- 通常来讲,同样的问题用递归写要比用迭代写代码量较少
使用递归实现1+2+。。。+99+100
- 思路:先找规律,在找边界
public static int f(int x) {
if (x == 1) { return 1; }
else { return f(x - 1) + x; } }
- 递归实现斐波那契数列
斐波拉契:除去第一项和第二项,前两项之和等于第三项
public static int f(int x) {
if (x == 1 || x == 2) { return 1; }
else { return f(x-1) + f(x-2); } } }
不用递归:
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;
2021/1/21
数组
主要是用于解决大量的数据计算与储存的问题
数组是java提供的一种最简单的数据结构,可以用来储存一个元素个数固定且类型相同的有序集。
数组在内存中的情况
栈:主要用于运行函数的内存
堆:主要 用于储存数据对象的内存
每一个数组而言,都存在堆内存当中,每个数组都是一个对象
数组是一个连续的储存结构
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210121172811164.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3F1YW54aW5xaW5n,size_16,color_F
数组本质上就是在堆内存中一系列地址连续且空间大小相等的存储空间(变量),每一个存
储空间用来存储数据(基本,引用)
数组是在堆内存中存储,称之为是一个对数对象,并且在堆内存中存储的数据都有 默认初始 化 的流程。所以数组创建之初,每一个存储空间里面都会被JVM初始化该数据类型对应的零值。
数组的地址是连续的,所以通过公式:An=A1+(n-1)*d可以快速访问到其他的元素,所以对于
数组而言查找元素比较快的。将元素的真实物理地址转换成对应的角标获取元素。
如何来调用数组呢?通过一个变量存储该数组在堆内存当中的首元素的地址。
当数组一旦定义出来,其长度不可变,存储空间的内容是可变的
所以我们在定义数组的时候,要么把长度固定,要么直接输入相关的元素。
数组的定义方式
//创建一个指定长度且指定数据类型的一维数组,名称为数组名,虽然没有指定元素,但是会有默认值
数据类型[] 数组名 = new 数据类型[长度];
//创建一个指定元素且指定数据类型的一维数组,名称为数组名,虽然有指定元素,还是有默认初始化这个步骤的!
数据类型[] 数组名 = new 数据类型[]{数据1,数据2,...,数据n};
数据类型[] 数组名 = {数据1,数据2,...,数据n};
常用的数组操作
- 数组扩容问题
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]); } }
//在指定的数组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; } }
选择排序算法
思路:从前往后依次,与后面没有数比较
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210121173659730.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3F1YW54aW5xaW5n,size_16,color_FFFFFF,t_70#pic_center
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; } }
冒泡排序算法
思路:
![在这里插入图片描述](https://img-blog.csdnimg.cn/2021012117473153.png#pic_center
插入排序算法
思路:
二分法查找算法
有个前提,所查找的数据集必须是有序的(升序,降序)
思路:先找到这个数据集最大,和最小的,再找出中间值,用要查的数去比较中间值,然后再次,直到找到这个值
2021/1/22
计数排序算法
- 思路:首先找出一组数据中最大值和最小值,然后新建一个数组来存放每个数的出现的次数,然后找出数与角标的关系(number=index+min),遍历原数组找每个数出现的次数,遍历新建的数组打印数字顺序
public class Semple01 {
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];
// 先找出最大值和最小值
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
if (arr[i] < min) {
min = arr[i];
}
}
// 新建一个数组
int[] temp = new int[max - min + 1];
for (int i = 0; i < arr.length; i++) {
temp[arr[i] - min]++;
}
int k = 0;
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 Semple02 {
public static void main(String[] args) {
int[] arr = { 102, 203, 321, 13, 12, 78, 96, 34, 37, 28, 6, 8, 5, 6 };
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
int radex = (max + "").length();
LinkedList<Integer>[] queues = new LinkedList[10];
for (int i = 0; i < queues.length; i++) {
queues[i] = new LinkedList<Integer>();
}
// 对数字分类
for (int r = 0; r < radex; r++) {
for (int i = 0; i < arr.length; i++) {
int index = getIndex(arr[i], r);
queues[index].offer(arr[i]);
}
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;
int index = 0;
for (int i = 0; i <= r; i++) {
index = number % 10;
number = 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(", ");
}
}
}
}
2021/1/24
二维数组
本质上:就是一个一维数组,只不过该一维数组里面的元素是另一个一维数组
二维数组的定义
数据类型[][] 矩阵名 = new 数据类型[row][col];
数据类型[][] 矩阵名 = new 数据类型[][] { {...}, {...}, {...} };
数据类型[][] 矩阵名 = { {...}, {...}, {...} };
例题
输入8个点坐标,然后计算这些点中,那两个点的距离是最近的
- 思路:先获取输入的坐标,先随便两个点的距离为最短,然后循环,当前点的距离与最短距离比较,如果短,就把记住这个坐标
五子棋
2021/1/26
Demo83
Demo85
- 先排序,再找出最大公约数
Demo88
- 先输入球的个数和槽子的个数 ,拼接每个路径,先循环,再随机0和1,来判断L和R,再输出
Demo90
- 思路:先循环,再循环后面数字是否与与第一个数字相同,次数加一,当次数大于等于4是就结束循环
八皇后问题
2021/1/26
leetCode283
class Solution {
public void moveZeroes(int[] nums) {
int k = 0;
int temp = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
temp=nums[i];
nums[i] = nums[k];
nums[k] = temp;
k++;
}
}
}
}
LeetCode905
- 思路:双指针
class Solution {
public int[] sortArrayByParity(int[] A) {
int k = 0;
int temp = 0;
for (int i = 0; i < A.length; i++) {
if (A[i] % 2 == 0) {
temp = A[i];
A[i] = A[k];
A[k] = temp;
k++;
}
}
return A;
}
}
LeetCode1013
LeetCode724
LeetCode209
- 思路:先循环。算出数字之和,在循环,子数组的长度,在减去当前数字
2021/1/28
封装和private关键字
常见的封装体现
- 函数
- 类
封装有什么好处
- 提高了安全性
- 隐藏一些不需要被外界获知的内容
- 提高了代码复用性
- 也面向对象 三大特点:封装,继承,多态
private关键字,属于权限关键字,private可以作用于对象的属性和行为,外界创建的对象后,不能访问被peivate修饰的内容
public class Sample01 {
public static void main(String[] args) {
Person p1 = new Person();
/* p1.name = "狗蛋"; p1.age = 10; p1.speak(); p1.age = -10; p1.speak(); *//* System.out.println(p1.age); //比较无辜 */
p1.setName("旺财");
// p1.setName("小强");
p1.setAge(10);
p1.speak();
}
}
class Person {
private String name;
private int age;
private int mathScore;
public void speak() {
System.out.println("我是" + name + ",我今年" + age + "岁");
}
public void setMathScore(int newMathScore) {
mathScore = newMathScore;
}
public void setName(String newName) {
if (newName.equals("旺财")) {
name = "哈士奇";
} else {
name = newName;
}
}
public void setAge(int newAge) {
if (newAge < 0) {
age = 0;
} else {
age = newAge;
}
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
总结
- 类中不需要对外界提供的内容,最好都私有化
- 如果后续真的需要对私有内容进行修改,最好加上setXXX修改器、getXXX访问器
不可变对象或者类
就是指其内部的数据都是私有的,没有向外界提供任何修改内部的方法(String)
- 所有的数据都是私有的
- 没有修改器的方法
局部变量和成员变量
代码执行流程:
- javac 编译Sample.java源代码 生成Sample.class和Person.class两个字节码文件
- 如果java Person ,运行Person字节码文件,则报错,没有主函数不是主类
- 只能java Sample 运行Sample程序
- 将相关的字节码(Sample.class Person.class)文件加载进JVM中内存下的方法区
- 在方法区中Sample字节码所在的区域里,找主函数,将主函数的栈帧加载进栈内存开始运行
- 开始执行主函数的第一句代码,创建Person对象
- 在堆内存中开辟一个空间并分配地址,在该空间中创建成员变量并默认初始化
- 在主函数空间中创建局部变量p1,并将该对象的地址传给p1 9. 接着执行主函数第二句代码,调用p1对象的setName方法
- 从方法区中的Person里,将setName函数栈帧加载进栈,主函数暂停运行
- setName进栈后,创建局部变量name(形参),并将实参“小强”这个字符串在字符串常量池
中的地址赋予name 12. 因为setName成员函数只有一份在方法区中Person所属区间里,之后可以被多个同类对象调
用,为了区分到底是哪个对象调用的该方法,所以在每一个成员函数中,都会有一个隐藏的
关键字数据 this ,this相当于一个变量来存储当前对象的地址。(当前对象的引用) - 执行setName中的内容,如果数据没有问题的话,就将局部变量的值赋值个当前对象的成员
变量 - setName函数执行最后一行隐藏的return,表示函数结束并弹栈
- 主函数成为当前栈顶,继续执行
- 执行p1调用setAge函数,从方法区中Person所属空间里找setAge这一段代码,将该函数栈帧加
载进栈内存成为新的栈顶,则主函数暂停,该函数运行。先创建形参age的局部变量,接收实
参传来的值10,为了区分对象的调用关系,自带this关键字数据,this存的还是p1的地址,如
果age没有问题,则将10传给this所指向的对象中age这个成员变量。setAge执行最后一行隐藏
的return,表示函数结束并弹栈 - 主函数称为新的栈顶继续执行,调用p1的speak函数进栈
- 在方法区中Person字节码所属空间里读取speak代码,将该栈帧加载进占内存中,主函数暂
停,该函数执行,无形参只能表示没有形参的局部变量,但是在函数内部也可以创建其他的
局部变量,并且有this关键数据存的是p1的地址,然后去打印name和age,由于speak空间中
已经没有其他名为name或age的局部变量,所以找不到,接着找this对象中的数据,找到了则
打印。直至函数结束并弹栈 - 主函数又称为栈顶,也没有代码了,执行隐藏的return,主函数弹栈,表示程序结束
局部变量和成员变量有什么区别
- 生命周期
成员变量随着对象的创建而创建,随着对象的消亡而消失
局部变量随着函数的进栈而创建,随着函数的出栈而消失 - 存储位置
成员变量在堆内存中对象所属空间里
局部变量在栈内存中函数所属空间里 - 定义位置
成员函数在类中,函数外定义
局部变量在函数中定义 - 初始化
成员变量有默认初始化
局部变量必须初始化之后再调用
2021/2/23
- Demo108
public class Demo108 {
public static void main(String[] args) {
Fan fan1 = new Fan();
Fan fan2 = new Fan();
fan1.setSpeed(Fan.FAST);
fan1.setRadius(10);
fan1.setColor("yellow");
fan1.setOn(true);
fan2.setSpeed(Fan.MEDIUM);
fan2.setRadius(5);
fan2.setColor("blue");
fan2.setOn(false);
System.out.println(fan1.toString());
System.out.println(fan2.toString());
}
}
class Fan {
public static final int SlOW = 1;
public static final int MEDIUM = 2;
public static final int FAST = 3;
private int speed = 1;
private boolean on = false;
private double radius = 5;
public String color = "blue";
public Fan() {
}
public void setSpeed(int speed) {
this.speed = speed;
}
public void setOn(boolean on) {
this.on = on;
}
public void setRadius(double radius) {
this.radius = radius;
}
public void setColor(String color) {
this.color = color;
}
public int getSpeed() {
return speed;
}
public boolean isOn() {
return on;
}
public double getRadius() {
return radius;
}
public String getColor() {
return color;
}
public String toString() {
if (!on) {
return "fan is off";
}
return "风扇的速度:" + speed + "\n颜色:" + color + "\n半径:" + radius;
}
}
- Demo109
public class Demo109 {
public static void main(String[] args) {
}
}
class RegularPolygon {
private int n = 3;
private double side = 1;
private double x = 0;
private double y = 0;
public RegularPolygon() {
}
public RegularPolygon(int newn, double newside) {
n = newn;
side = newside;
x = 0;
y = 0;
}
public RegularPolygon(int newn, double newside, double newx, double newy) {
n = newn;
side = newside;
x = newx;
y = newy;
}
public void setn(int newn) {
n = newn;
};
public void setside(double news) {
side = news;
};
public void setx(double newx) {
x = newx;
};
public void sety(double newy) {
y = newy;
};
public int getn() {
return n;
};
public double getside() {
return side;
};
public double getx() {
return x;
};
public double gety() {
return y;
};
public double getPerimeter() {
return n * side;
}
public double getArea() {
return (n * side * side) / (4 * Math.tan(Math.PI / n));
}
}
- Demo112
public static void main(String[] args) {
Time t1 = new Time();
System.out.println(t1.toString());
Time t2 = new Time(123123123123L);
System.out.println(t2.toString());
Time t3 = new Time(11,6,52);
System.out.println(t3.toString());
t3.setTime(System.currentTimeMillis());
System.out.println(t3.toString());
}
}
class Time {
private long hour; private long minute;
private long second;
public Time() {
this(System.currentTimeMillis());
}
public Time(long millis) {
hour = cacluHour(millis);
minute = cacluMinte(millis);
second = cacluSecond(millis);
}
public Time(long hour, long minute,long second) {
this.hour = hour;
this.minute = minute;
this.second = second;
}
public void setTime(long elapseTime) {
hour = cacluHour(elapseTime);
minute = cacluMinte(elapseTime);
second = cacluSecond(elapseTime);
}
public String toString() {
return hour + ":" + minute + ":" + second;
}
public long getHour() {
return hour;
}
public long getMinute() {
return minute;
}
public long getSecond() {
return second;
}
private long cacluHour(long millis) {
return millis / 1000 / 60 / 60 % 24; }
private long cacluMinte(long millis) {
return millis / 1000 / 60 % 60; }
private long cacluSecond(long millis) {
return millis / 1000 % 60; } }
- Demo113
public class Demo113 {
public static void main(String[] args) {
MyInteger m1 = new MyInteger(3);
System.out.println(m1.isEven());
System.out.println(m1.isOdd());
System.out.println(m1.isPrime());
MyInteger m2 = new MyInteger(4);
MyInteger m3 = new MyInteger(13); System.out.println(MyInteger.isEven(m2)); System.out.println(MyInteger.isPrime(m3)); System.out.println(m2.equals(m3)); System.out.println(MyInteger.parseInt("1234") + 1); } }
class MyInteger {
private int value;
public MyInteger(int value) {
this.value = value;
}public int get() {
return value;
}
public boolean isEven() {
return value % 2 == 0;
}
public boolean isOdd() {
return value % 2 == 1;
}
public boolean isPrime() {
for (int i = 2; i <= value / 2; i++) {
if (value % i == 0) { return false; } }
return true;
}
public static boolean isEven(MyInteger integer) {
return integer.get() % 2 == 0; }
public static boolean isOdd(MyInteger integer) {
return integer.get() % 2 == 1; }
public static boolean isPrime(MyInteger integer) {
for (int i = 2; i <= integer.get() / 2; i++) {
if (integer.get() % i == 0) {
return false; } }
return true; }
public boolean equals(int num) {
return value == num; }
public boolean equals(MyInteger integer) {
return value == integer.get(); }
//"1234" // i //4*10^0 + 3*10^1 + 2*10^2 + 1*10^3
public static int parseInt(String str) {
int result = 0;
for (int i = 0; i < str.length(); i++)
{ int num = str.charAt(i) - '0'; result = num + result * 10;
}
return result; } }
- Demo114
public class Demo114 {
public static void main(String[] args) {
MyPoint p1 = new MyPoint(3,3);
MyPoint p2 = new MyPoint(4,4);
System.out.println(p1.distance(p2));
System.out.println(p1.distance(0,0));
double[] point1 = {1,2};
double[] point2 = {3,4};
double distance = distance(point1,point2);
System.out.println(distance);
}
public static double distance(double[] p1,double[] p2) {
return Math.hypot(p1[0] - p2[0],p1[1] - p2[1]);
}
}
class MyPoint {
private double x;
private double y;
public MyPoint() {
this(0,0);
}
public MyPoint(double x,double y) {
this.x = x; this.y = y;
}
public double distance(MyPoint point) {
return distance(point.getX(),point.getY());
}
public double distance(double x,double y) {
return Math.hypot(this.x - x , this.y - y);
}
public double getX() {
return x;
}
public double getY()
{
return y;
}
}
- Demo115
public class Demo115 {
public static void main(String[] args) {
Queue queue = new Queue();
System.out.println(queue);
for(int i = 1; i <= 10; i++) {
queue.enqueue(i);
}
System.out.println(queue);
for (int i = 1; i <= 6; i++) {
System.out.println(queue.dequeue());
System.out.println(queue);
}
}
}
class Queue {
private int size; //队列中有效元素的个数
private int capacity = 8; //队列容器的最小容量 默认
private int[] element; //队列容器用于存储元素
element.length == size //表示队列已满
public Queue() {
element = new int[capacity];
size = 0;
}
public boolean isEmpty() {
return size == 0;
}
public int size() {
return size;
}
public void enqueue(int v) {
if (size == element.length) { //满了需要扩容 resize(element.length * 2); }element[size++] = v; }
public int dequeue() {
if (isEmpty()) {
return -1; //-1表示一种错误
}
int ret = element[0];
for (int i = 1; i < size; i++) {
element[i - 1] = element[i];
}
size--;
if (size <= element.length / 4 && element.length > capacity) {
//需要缩容
resize(element.length / 2); }
return ret; }
private void resize(int newlength) {
int[] newelement = new int[newlength];
for (int i = 0; i < size; i++) {
newelement[i] = element[i];
}
element = newelement;
}
public String toString() {
//封装对象的信息 用于打印 String s = "[";
if (isEmpty()) { s += "]";
}
else
{
for (int i = 0; i < size; i++) {
if (i == size - 1) {
s = s + element[i] + "]";
}
else {
s = s + element[i] + ",";
}
}
}
return s;
}
}
- 自定义String
public class Demo117 {
//目前忽略掉的一些问题:数据合法性问题 时间复杂度
public static void main(String[] args) {
char[] chars = {'a','b','c'};
MyString s1 = new MyString(chars);
MyString s2 = new MyString("ab");
System.out.println(s1.compareTo(s2));
MyString s3 = new MyString("ABCD123abcdKKK");
s3.show();
MyString s4 = s3.toLowerCase();
s4.show(); s3.show();
MyString s5 = new MyString("ABC");
MyString s6 = new MyString("abd"); System.out.println(s5.compareToIgnoreCase(s6));
s5.concat(s6).show();
MyString s7 = new MyString("123456");
MyString s8 = new MyString("789");
System.out.println(s7.contains(s8));
MyString s9 = new MyString("xxx.avi");
MyString s10 = new MyString("avi");
System.out.println(s9.endsWith(s10));
MyString s11 = new MyString("abc");
MyString s12 = new MyString("abd");
System.out.println(s11.equals(s12));
MyString s13 = new MyString("abc");
MyString s14 = new MyString("ABC"); System.out.println(s13.equalsIgnoreCase(s14));
MyString s15 = new MyString("123123123");
s15.replace('2','4').show();
System.out.println(s15.startsWith(new MyString("123"))); s15.substring(3,7).show();
}
}
class MyString {
//字符串本身就是一个字符数组 只不过我们不能在该数组中修改元素
private char[] data;
public MyString(char[] chars) {
data = new char[chars.length];
for (int i = 0; i < chars.length; i++) {
data[i] = chars[i];
}
}
public MyString(String s) {
data = new char[s.length()];
for (int i = 0; i < s.length(); i++)
{
data[i] = s.charAt(i);
}
}
public MyString(MyString s) {
data = new char[s.length()];
for (int i = 0; i < s.length(); i++) {
data[i] = s.charAt(i);
}
}
public MyString substring(int beginIndex,int endIndex) {
//[begin,end) [1,4)
char[] chars = new char[endIndex - beginIndex];
int index = 0;
/*123456789 b ei */
for (int i = beginIndex; i < endIndex; i++) {
chars[index++] = data[i];
}
return new MyString(chars);
}
public boolean startsWith(MyString s) {
/*123456 i123 j*/
int i = 0;
int j = 0;
while (true) {
if (charAt(i) == s.charAt(j))
{
i++; j++; if (j >= s.length())
{
return true;
}
}
else { return false;
}
}
}
//自己写
public MyString replace(MyString oldString,MyString newString) { /*123123123 23-66 166166166 */
return null;
}
public MyString replace(char oldChar,char newChar) {
/*123123123 143143143 2->4 */
char[] chars = new char[length()];
for (int i = 0; i < length(); i++) {
if (charAt(i) == oldChar) {
chars[i] = newChar;
}
else { chars[i] = data[i];
}
}
return new MyString(chars);
}
public int indexOf(char c)
{
for(int i = 0; i < length(); i++) {
if(charAt(i) == c) {
return i;
}
}return -1;
}
//自己写
public int indexOf(MyString s) {
//123456 // 45 //->3 return -1;
}
//自己写
public int lastIndexOf(char c) { return -1; }
//自己写
public int lastIndexOf(MyString s) {
//123456784578 // 45 //->8
return -1;
}
public boolean equalsIgnoreCase(MyString s) {
return compareToIgnoreCase(s) == 0;
}
public boolean equals(MyString s) {
return compareTo(s) == 0;
}
public boolean endsWith(MyString s) {
/*xxxx.avii avij */
int i = length() - 1;
int j = s.length() - 1;
while (true) {
if (charAt(i) == s.charAt(j)) {
i--; j--; if (j < 0) { return true;
}
}
else {
return false;
}
}
}
public boolean contains(MyString s) {
//KMP算法 /* i k1 12335678j k2 456l */
char[] k1 = data;
char[] k2 = s.data;
for (int i = 0; i <= k1.length - k2.length; i++) {
if (k1[i] == k2[0]) {
int j = i + 1;
for (int l = 1; l < k2.length; l++,j++) {
if (k1[j] != k2[l]) {
return false;
}
}
return true;
}
}
return false;
}
public MyString concat(MyString s) {
char[] chars = new char[length() + s.length()];
int index = 0;
for (int i = 0; i < length(); i++)
{ chars[index++] = data[i];
}
for (int i = 0; i < s.length(); i++) {
chars[index++] = s.charAt(i);
}
return new MyString(chars);
}
public MyString toLowerCase() {
char[] chars = new char[length()];
for (int i = 0; i < data.length; i++) {
char c = data[i];
if (isUpperLetter(c)) {
//'a' 97 //'A' 65
chars[i] = (char)(c + 32);
}
else {
chars[i] = c;
}
}
return new MyString(chars);
}
private boolean isUpperLetter(char c) {
return c >= 'A' && c <= 'Z';
}
/*自己写 */
public MyString toUpperCase(){
return null;
}
public void show() {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]);
}
System.out.println();
}
public int compareToIgnoreCase(MyString s) {
MyString temp1 = toLowerCase();
MyString temp2 = s.toLowerCase();
return temp1.compareTo(temp2);
}
public int compareTo(MyString s) {
int i = 0; int j = 0; while(true) {
if (charAt(i) == s.charAt(j)) {
i++; j++;
if (i == length() && j == s.length()) {
return 0;
}
if (i < length() && j >= s.length() || i >= length() && j < s.length()) { return length() - s.length();
}
} else
{
return charAt(i) - s.charAt(j);
}
}
}
public char charAt(int index) {
return data[index];
}
public int length() {
return data.length;
}
}
2021/3/07
乱码?–编码格式
- ascii码 0~128 一个字符一个字节
- unicode 编码 1个字符存2个字节
- utf-8 编码 1个字节 2个字节 3个字节
- gbk 国标码 gb2312 big5 支持繁体字
包与权限
包
- 包其实相当于系统的文件夹
- 包的声明必须位于第一行非注释语
权限
- public 共有的 类内部、同包、不同包
- protected 受保护的 类内部、同包、不同包的子类
- default 默认的 类内部、同包
- private 私有的 类内部(ok) 同包(否) 不同包(否)
- public>protected>default>private
枚举
- enum 可以当成数据类型来用管理一系列的常量(限定取值)
- 由来:枚举出来之前都是拿class或者interface来组织管理常量—基本的数据类型
- 缺点:只要数据类型合适,就会编译通过,不考虑实际的业务,可能造成错误
- Enum的子类:不能再继承别的类
常用类
常用类:JDK给提供出来的一些类
Object类
- Object是所有类的父类,如果一个类没有extends一个类,那它是继承了Object。
- 类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。
- 功能:指示其他某个对象是否与此对象“相等”。其实是比较对象的地址的!!!
- 重写的场景:如果容器存储多个对象,需要判断其中是否包含某个对象
== 比较对象的地址
String类的equals(Object obj) :比较值是否相等 “abc” “abc”
功能:返回的是对象所属类的字节码对象(类的完全限定名)
public final native Class<?> getClass();
native 本地的,修饰的方法,没有方法体,但是不代表没有实现,通常是由C/C++来实现的
Class 类 :字节码文件的类型 也是对象 待后续学反射的时候会详细讲
System.out.println(stu3.getClass()==stu4.getClass());//判断不同对象的Class对象是否相同
返回结果是true,说明类只加载一次
public native int hashCode();
- 功能:返回对象的哈希值。默认返回对象的地址。允许子类重写。
public String toString() {}
- 功能:把当前对象转换成字符串形式,未重写时,返回 :类的完全限定名+@+哈希值的十六进制字符串可以继承,可以重写
finalize() : 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
垃圾回收器 GC–不存在对该对象的更多引用
StringBuffer类
- 线程安全的可变字符序列。synchronized 同步锁 线程安全—适合多线程
- 可变字符序列:一个类似于 String 的字符串缓冲区
- StringBuffer append(XXX) 往末尾添加
- StringBuffer insert(int offset, String str) 指定位置添加
- StringBuffer reverse() 反转
StringBuilder类
- 一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步 ,非线程安全—适合单线程
String 类
- 其值在创建之后不能更改,可以共享 本质 是char value[]
- String str=“abc”; 内存的方法区有一个字符串常量池,先去判断常量池中是有"abc"如果没有,就创建一个,放在常量池中,把地址给strString str2=“abc”; 如果有,直接把地址赋值给str2 str、str2共同指向同一个地址,这就叫共享。