JAVA笔记


# FOR的使用
1. for(int=1; i<=10;i++``){syso}
2. for 和 while 的区别:for里的int 是在括号里的,在循环内部,会被自动回收,提高内存使用效率。 while 里的int变量是不会被回收的。截图区别
3. do while: 先执行后判断,至少执行一次。
while:先判断后执行
# 补充
- 八大基本类型:1.整数:long short int 2. 小数 float double 3.字节:byte 字符:char 布尔值:boolean
- float和double不能放在一起 float a=2.33f; double b=2.33;
- long有八个字节,int有四个
- long c=5; int d=(long) c; 强制类型转变
- 1byte=8bit
- 强制类型转变: 类型 变量名=(要被转化的类型)值
如:int a=(long)10;
- break:结束当前循环 注:多层循环需要添加标签,标明跳到哪
- continue:跳过当前循环
- return:结束一个方法,结束所有
- i++:先执行再加一次 ++i:先加一次再执行
- 图片
- 比较大小的图片 图片
# 短路效应
- &&:双个代表只会判断前一个,若符合条件则后一个不会被执行,容易造成短路效应
- &:单个的前后两个都会执行一次
- ```
int a=1;
int b=1;
if(a++>0
System.out.println(a);
System.out.println(b);
}
```
# 字符图片代码
tupian
## 画笔工具
TUPAIN
# java概述
面向对象的编程语言
### JDK与JRE
- JDK:JAVA的开发和运行环境,JDK是给开发人员用的,其中包含了JAVA的开发工具以及JRE,所以安装了JDK就不用安装JRE了。
- JRE:JAVA的运行环境,其中包括虚拟机和JAVA程序所需的核心类库等,如果想要运行一个开发好的JAVA程序,电脑就只需安装JRE。
- 虚拟机:JAVA运行的所有变量都是跑在内存上的,虚拟机就是在实际内存上开辟一块区域,所有的JAVA程序都是运行在虚拟机上的,与电脑的实际操作系统无关,所以JAVA就可以在各种系统中运行
- 各种操作系统的CPU处理方式不同,内存设计不同导致同一个程序不能在各种操作系统中运行,所以就出现了虚拟机的功能
### JAVA三个体系
- JavaSE--------标准版 开发客户端 ,并不能做网站
- JavaEE--------(Enterprise Edition)企业版、网站、服务端 EE包含SE
- JavaME-------移动端
### JAVA与C++的不同及JAVA的优点
- C++是面向过程的编程语言
- JAVA可以 垃圾自动回收
- JAVA可以 多线程(多个任务同时进行)
- 跨平台(环境不同一样可以运行),一次编译,到处运行
### JAVA环境安装
- 找到环境变量,编辑系统变量
- 变量名命名为:JAVA_HOME
- 变量值为JDK的下载路径,进入到能看到bin的目录,不进bin
- 修改系统变量中的path,复制:%JAVA_HOME%\bin 及 %JAVA_HOME%\jre\bin
- 注:WIN7两句话需要用分号隔开
- 验证是否安装完成,打开小黑窗,分别输入java javac
- eclipse安装企业版的,就是Enterprise
# Eclipse基本使用方法
- 隐藏左方行数:空白区域,右键————Show Line Numbers
- 挑选最下方的视窗: Window--Show View
- 格式化:Source----Format
# 小知识点:
- 自己写的代码是 .JAVA,经过编译之后是 .class
- 输出语句中 System.out.println();的换行,是在打印完括号内的内容后才进行换行
- 自己命名的标识符不能用数字打头,且不能是JAVA里的关键字(如: int int=1),这样是不行的
- 在使用long时,如果超过了Int的表示范围,即超过21亿的范围,需要在赋值后面加上大写L(如:long a=222L),小数的float在赋值时也需要加上f。
- a++与++a:
- a++是先执行一次a,再对a进行加一
- ++a先对a进行加一,再执行a
- 快捷键:ctrl+alt+↓是快速复制选中行   Ctrl+d是删除     Alt+↑是往上对调换位置
# 八大基本类型
- 整数:
- short 2个字节,默认值0 ,占8个bit
- int 4个字节,默认值0, 占16个bit
- long 8个字节,默认值0L,占32个bit
- 小数:
- float 4个字节,默认值0.0f
- double 8个字节,默认值0.0d
- 字节: byte 1字节,默认值0,表示范围为 -128~127
- 一个字节占8位,最大值127用二进制表示为 0111 1111,(即:1+2+4+8+16+32+64=127)第一位表示正负号:0为正,1为负
- 最小值-128用二进制表示为:1000 0000   这个二进制表示128,同时第一位为1,表示负的,所以是-128
- 举例:127加2之后是-127
- 如:127的二进制是0111 1111,加1之后1000 0000是128,但是一个字节只有8位,不能再往前进1,二进制的第一位表示正负号,所以变成了-128,这时候再加1,就是-127
- 其实就是一个首尾相连的圈,127再加的话就到了-128,-128再减的话就到了127
- 字符:char 2字节 表示范围为 0~65535
- 布尔值:Boolean 理论上是1bit,但单个 使用往往占4个字节,具体视所处编译环境。
#### int和char依据ASCII表可以相互转换
char i=97,使用输出语句后输出的是字母a ,就是依据ASCII表找出97对应的字母。
# 二进制
由1开始,之后呈2的指数倍增加
8 4 2 1
- 0001————1
- 0010————2
- 0100————4
- 1000————8
- 1000 0————16
- 1000 00————32
用二进制表示15为:1+2+4+8 即为1111
用二进制表示127为:128-1 即为10000000-0001 01111111
# 运算符
- 除法中使用int时:
- int a=9; int b=6; int c=a/b; System.out.println(c); 答案为1.
- 因为c是整数,所以除法不能整除时,只输出商
- 取余时:
- x%?= 结果的范围是 0~x-1
- 想要有x种情况,就对x+1取余
### 缩写
- a=a+1 可以写为 a++
- a=a+6 可以写为 a+=6
# 位运算符
### 按位与(&)
- 两个数都为true(1),那么答案为true(1)
- 如:7&5=5
- 7的二进制为0111   5的二进制为0101   每一位都&   结果为0101   换算为十进制就是5
- 如:13&7=5
- 13:   1101      7:   0111      每一位都&      结果为0101     换算为十进制为5   
### 按位或(
- 两个数有一个是true(1),那么答案为true(1)
- 如:13
- 13: 1101       7: 0111   每一位都对应的
### 按位异或(^)
- 两个数都为true(1)或者都为false(0),那么异或的结果为false(0),两数一个为true,一个为false,结果为true(1)
- 一个数对另一个数异或两次,该数本身不变
- 两数数值的交换,如:a=5,b=9
- 第一种方法:定义一个c,c=a,a=b,b=c
- 第二种方法:a=a^b     b=a^b   a=a^b
- 第一步的a=a^b    那么b=a^b时   将a替换为a^b  :  b=abb,依据上面的结论,a连续异或两次b,a的值不变,那么b=a;第三步:将a替换为a^b, b在上一步已经变成a了,那么  a=aba,依据结论 a=b;
- 异或交换其实就是依据结论:将a赋值给b,直接将a异或两次b:b=abb 之后再将b赋值给a,依据结论:a=baa,但是,前提必须先将a=ab,之后再根据结论将ab的部分替换为a就可以了
- 第三种方法:a=a+b b=a-b//a+b-b-------a a=a-b//a+b-a-----b
# 左移运算与右移运算
- 二进制的左右移动:1000>>2 : 0010 1101>>2 : 0011
### 结论:
- 对于一个正整数来说,左移几位,相当于乘以2的几次方,右移几位,相当于除以2的几次方
- 如:32>>3 :4       转换为二进制就为:10 0000>>3:0100
- 用最有效率的方法计算2*8的结果
- 直接左移右移就是最有效率的方法
- 2*8就是左移三位 答案为:2<<3;
# switch
语句:
int task=5;
switch(task){
case 1:
? System.out.println("登录功能");
? break;
case 2:
? System.out.println("2222");
? break;
default:
? System.out.println("默认");
? break;
}
IF主要用来判断是或者不是,如果是会.......不会的话会.....,switch用于明确情况的判断,确认执行的是哪一种命令。并且switch是不能写范围的,比如成绩在某某之间。
jdk5之前,switch不支持String 和 枚举
# while循环
语句:
int j=1;
while(j<=10){
? System.out.println(111);
? j++;
}j++写在花括号里面
#### for循环和while循环的区别:
JAVA的垃圾自动回收机制,for循环的Int定义在小括号里面,出了小括号后面的代码访问不到,性能角度看for循环的效率更高一点,不会创作许多无用的变量。while循环的Int定义变量在花括号外面,后面的代码可以访问到。
#### do while循环:
int k=1;
do{
? System.out.println();
? k++;
}while(k<=10);
#### 死循环
- for(;??{
? System.out.println();
}
- while(true){
? System.out.println();
}
#### 跳出循环:
- break:
- 跳出(结束)当前循环
- break标签(用于跳出多重嵌套循环): 在想要结束的位置加上标签和冒号,之后在break后面写上标签名
- continue:
- 跳过当前循环
- return:
- 结束当前方法,后面所有的代码没有意义,系统会提醒删掉
# 数组
属于引用类型
### 注:
- 数组的元素都是同一类型
- 是一个集合(与collection集合区分),仅指放的是一堆东西
### 一维数组:
语法:
- Int[] a;
- int a[];
数组必须初始化才能使用
- 静态初始化:
- int[] a={1,3,4,5};
- 动态初始化:
- int[] b=new int[3];
- b[0]=1; b[2]=5; 给元素赋值
- 获取数组的某一个元素
- System.out.printlin(a[0]);
##### 获取每一个元素:
- for(int i=0;i<=a.length();i++){
? System.out.println(a[i]); }
- 倒叙输出:
- for(int i=a.length()-1;i>=0;i--){
System.out.printlin(a[i]); }
### 二维数组
语法
- int[] [] a;
- int b[] [];
- int[] c[];
初始化:
- 静态初始化:
- Int[] [] a={{1,2,3},{4,5},{8}};
- 动态初始化:
- int[] [] b=new int[5] [];
- 获取二维数组中的每一个元素:
for(int i=0;i
? for(int j=0;j
? System.out.print(a[i] [j]); }
? System.out.prinln(); }
# Arrays类(工具类)
(1) int binarySearch(type[] a,type value):使用二分法查询value元素值在a数组中出现的索引位
置,如果a数组不包含value元素值,则返回负数。该方法要求数组已经按照升序进行了排列。
(2) int binarySearch(type[] a,int fromeIndex,int toIndex,type value):与上一个方法名相同,参数
不同,称为方法重载,同样要求数组已经按照升序进行了排列。
(3) type[] copyOf(type[] original,int newLength):这个方法会把original数组复制成一个新数组,
其中newLength是新数组的长度,当newLength大于original的长度时,新数组的前面元素就是original
的所有元素,后面所有元素使用数组类型默认值进行补充。
(4) type[] copyOfRange(type[] original,int fromIndex,int toIndex):这个方法只复制original数值的
from索引到to索引的元素。
public class Student {
static {
System.out.println("Student 静态代码块");
}
{
System.out.println("Student 代码块");
}
public Student() {
System.out.println("Student 构造方法");
}
}
public class StudentTest {
static {
System.out.println("北大吴彦祖");
}
public static void main(String[] args) {
System.out.println("我是main方法");
Student s1 = new Student();
Student s2 = new Student();
}
}
(5) boolean equals(type[] a1,type[] a2):如果数组a1与数组a2的长度相同,并且数值a1中元素值
与a2中元素值相同,该方法返回true。
(6) void fill(type[] a,type val):该方法对数组进行赋值,将所有元素赋值为val
(7) void fill(type[] a,int fromIndex,int toIndex,type val):该方法仅仅对从fromIndex开始到toIndex
索引的的元素进行赋值,赋值为val
(8) void sort(type[] a):该方法对数组a中的元素进行排序。
(9) void sort(type[] a,int fromIndex,int toIndex):对数组a中的从fromIndex开始到toIndex的元素
进行排序。
(10) String toString(type[] a):该方法将一个数组转换成一个字符串。按顺序把多个数组元素连缀在
一起,多个数组元素使用英文逗号和空格隔开。
# Date类:
Date date=new Date();
System.out.println(date); 直接得到当前日期
System.out.println(date.getTime()); 返回毫秒值
# 日期格式化
#### 日期转换成字符串:
Date date=new Date();
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd");
String aa=dateFormat.format(date);
System.out.println(aa);
#### 字符串转换成日期:
String aa="2000-11-11";
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd");
Date brith=dateFormat.parse(aa); 这里需要抛出异常
System.out.println( brith);
# Calendar
语句:
? Calendar calendar=Calendar.getInstance();
- 这里不需要new一个Calendar,getInstance表示初始化这个类
- 因为Calendar是一个单例
- Calendar和Date都是表示日期的工具,他们可以相互转换。
- ```
Calendar cal=Calendar.getInstance();
Date date=cal.getTime();
System.out.println(date);
Calendar cale=Calendar.getInstance();
Cale.setTime(date);
```
#### Calendar类提供的常用方法:
- calendar.add(Calendar.DATE,-2);
- 小括号内,逗号前的表示要修改的属性,后面数字写要修改的值
- System.out.println(calendar.get(Calendar.DATE));
- 举例:在除夕当晚最后一秒,add一秒
```
Calendar cal = Calendar.getInstance();
System.out.println(cal.getTime());
cal.set(2021, 1, 15, 23, 59, 59);
cal.add(Calendar.SECOND, 1);
System.out.println(cal.getTime());
```
- calendar.get(int field); 返回指定日历字段的值
- 如: System.out.println("年:" + cal.get(Calendar.YEAR));
- System.out.println("月:" + (cal.get(Calendar.MONTH) + 1));月份的下标从0开始,所以取月份要加1
- System.out.println("日:" + cal.get(Calendar.DAY_OF_MONTH));
- System.out.println("时:" + cal.get(Calendar.HOUR_OF_DAY));
- System.out.println("分:" + cal.get(Calendar.MINUTE));
- System.out.println("秒:" + cal.get(Calendar.SECOND));
- calendar.getActualMaximum(int field); 返回指定日历字段的可能拥有的最大值
- calendar.getActualMinimum(int field); 返回指定日历字段的可能拥有的最小值
- calendar.roll(int field,int amout); 与add方法相似,区别在于超过该字段的最大范围时,也不会向上一个字段进位
- calendar.set(int field,int value); 将给定的日历字段设置为给定值
- cal.set(Calendar.YEAR, 2018);
- cal.set(Calendar.MONTH, Calendar.FEBRUARY);
- cal.set(Calendar.DAY_OF_MONTH, 15);
- cal.set(Calendar.HOUR_OF_DAY, 23);
- calendar.set(int year,int month, int date); 设置Calendar对象的年月日
- calendar.set(int year,int month,int date,int hourOfDay,int minute,int second);设置年月日时分秒
- cal.set(2018, 1, 15, 23, 59, 59);
- 注:在设置完成之后输出语句:System.out.println(cal.getTime());
# Random
语句:
? Random random=new Rondom();
#### next:
- random.nextInt();
- 返回int范围之内的一个随机数
- random.nextInt(100);
- 返回0~100以内的一个数,但是不包括100
# Math
### 方法:
- Math.sqrt(); 开根号
- Math.abs(); 求绝对值
- Math.floor(); 四舍五入 向下取整
- Math.round(); 四舍五入
# Bigdecimal
补:round是四舍五入,floor是向下取整
- double、float浮点数在进行基本运算时会发生数据丢失现象,需要用到bigdecimal。
语法:
? Bigdecimal decimal=new Bigdecimale(12.5);
#### 方法:
decimal.add(new Bigdecimal(3.5));
add是增加,指在decimal赋值基础上增加3.5
加减乘除的方法:
- add() 加法
- subtract() 减法
- multiply() 乘法
- divide() 除法
- pow(int n) 取余
# System
方法:
- System.getenv("path"); 获取指定的环境变量值
- System.getenv("JAVA_HOME");
- System.getProperty("user.name"); 获取用户名字
- System.getProperty("os.name"); 获取系统名字
- System.currentTimeMillis();
- 得到当前系统的毫秒值
# String
String是一个类,类才有对应的方法,不需要new,基本类型是一个关键字,没有对应的方法。
#### 方法:
String aaa="abcdef";
- System.out.println(aaa.charAt(2));
- charAt()是在括号内写上索引,返回对应的字符
- System.out.println(aaa.contains("abc"));
- contains()是在括号内写上内容,判断aaa字符串中是否包含,返回的是布尔值,判断为true或者false
- 也可以用indexof()查找字符串中是否包含某些字符,如果返回-1,就是不包含
- System.out.println(aaa.endsWith());
- endsWith()是在括号写上内容,判断aaa字符串中是否是以输入内容为结尾,返回布尔值
- System.out.println(aaa.equals());
- equals()是判断输入的内容是否和aaa中的内容完全相等,返回的是布尔值
- 不等于是   !aaa.equals(bbb)
- System.out.println(aaa.equalsIgnoreCase());
- 注:Ignore是忽略,Case是大小写
- equalsIgnoreCare()是判断内容是否相同,但是忽略了大小写
- System.out.println(aaa.indexof());
- indexof()是在括号内写上字符,返回对应的索引
- 注:括号内不论写多少字符,返回的只有第一个字符对应的索引,如果写出的字符,在字符串中查找不出,则返回负数
- System.out.println(aaa.isEmpty());
- isEmpty()判断字符串是否为空
- 注:bbb="" 与 bbb=null是不同的,只有前者可以用isEmpty()作判断
- System.out.println(aaa.replace(旧的字符,新的字符));
- replace()是替换,在逗号前输入旧的,即原本就有的字符,在逗号后输入新的,完成替换
- 注:替换完成后,原本的字符串并没有改变,而是创造了一个新的字符串,需要新命名来接收新的字符串
- System.out.println(aaa.split(","));
- String names="tom,jack,amy,daming"
- split()是分割字符串,在括号内写上分割的依据,例如names字符串是根据逗号来隔开
- 接收分割好的字符串时,用数组来接收:String[]   name=names.split(",");
- System.out.println(aaa.substring(2,7));
- substring()是截取字符串,中间可以加逗号填写两个数字,前面的数字表示从哪个字符开始截取,后面的表示截取到哪里,但是包前不包后,后面的索引对应的字符是不会被打印的
- System.out.println(aaa.toCharArray());
- toCharArray()返回的是数组,需要创建数组来接收:char[]  array=aaa.toCharArray();之后需要用for循环一个一个打印出来:for(int i=0;i
- System.out.println(aaa.toLowercase());
- toLowerCase()是把整个字符串转化成小写,与之相反是toUpperCase
- System.out.println(aaa.trim());
- trim()是去除空格,但并不是去除所有空格,只能去除前后的空格,在字符串中间的空格并不会被去除
- System.out.println(aaa.concat());
- 拼接字符串
- System.out.println(aaa.getBytes());
- 将字符串转化为二进制的数组
- ```
String a="abcde";
byte[] bytes=a.getBytes();
for(Integer i:bytes){
}
```
- 几乎每个类都可以getBytes
#### String 的内存结构
如:String a="hello"; a="bye";
hello一直存在,就算a的值发生了变化,但hello并没有消失,这就叫做String定义的字符串为一个常量,一旦被赋值,不可被改变
使用String a="hello";定义字符串时,系统会先去堆内存(常量池)中查找有没有hello存在,如果有则会直接返回该对象的地址,如果没有,则新建该对象再返回地址值。
如:String a="hello"; String b="hello";
hello在之前a的部分已经被创建过一次了,所以后面b的hello与a的hello是一样的,a与b同时指向一个hello,在常量池中不会存在两个hello
如果使用new String(“hello”); 会创建两个对象,new String()的部分会在堆内存中,"hello"会在常量池,同时,不管new String()多少次,堆内存中都会创建多个new String()
注:对于引用类型来说:==判断的是地址是否一样,equals方法是判断内容是否一样
重点:字符串如果是变量相加,先开空间,再拼接内容,既然开辟空间,那么地址一定不同                                 字符串如果是常量相加,先拼接,然后再常量池找,如果有就直接返回,没有再创建
# StringBuffer和StringBuilder
与String相比是可变的字符串
两者的区别:前者是线程安全的可变字符串,但是效率低,时间长。
? 后者线程不安全,但是效率高,时间短
buffer表示缓冲的意思
#### 构造方法:
- StringBuffer buffer=new StringBuffer();
- StringBuffer buffer2=new StringBuffer("12345");
- StringBuffer buffer3=new StringBuffer(60); 数字表示多大的容量,buffer3可以放多少数字
#### 常见方法:
- 添加:
- append
- buffer.append("hello");
- insert
- buffer.insert(3,"123");
- 表示在索引为3的地方插入123
- 删除:
- deleteCharAt
- buffer.deleteCharAt(0);
- 表示删除索引为0的字符
- delete
- buffer.delete(0,3);
- 表示从索引为0的地方删除到索引为3的地方,同样的包前不包后
- 替换
- replace
- 反转
- reverse
- buffer.reverse();
- 将字符串反转,倒过来
#### String与StringBuffer的互相转变
String bbb=buffer.toString();
### 将数字转变为字符串:
String a=String.valueOf(b);
# 包装类
- 各个基本类型对应的类:
- byte-----Byte
- char-----Character
- short-----Short
- float-----Float
- int-----Integer
- double-----Double
- long-----Long
- boolean-----Boolean
### String和int的互相转换:
- 其他类型转变为String:
- ```
int a=9;
String b=String.valueOf(a);
```
- 其他类型转变为int:
- ```
String a="9";
int b=Integer.parseInt(a);
```
### 进制之间的相互转换:
- 方法:
- 转换为二进制:
- int a=Integer.toBinaryString(32); 输出后a=100000;
- 转换为八进制:
- int a=integer.toOctalString(32); 输出后 a=40;
- 转换为十六进制:
- int a=integer.toHexString(32); 输出后 a=20;
- 其他的进制转换方法:
- String a=integer.toString(8,2); 输出后 a=1000;
- 第一个参数填要转化的数字(是int类型),第二个参数填要转化成哪一个进制
- 其他进制转换到十进制:
- int a=integer.parseInt("1000",2); 输出后 a=8;
- 第一个参数填字符串,要用引号引起来,第二个参数填当前的进制是哪一个进制,注意跟上面的区分
### 装箱与拆箱:
- 定义:
- 基本类型变成包装类叫装箱
- 包装类变成基本类型叫拆箱
- 自动装箱拆箱:
- ```
Integer a=6;
int b=a;
```
- 在装箱的过程中,如果a被赋的值在-128~127之间,会挑选软件划分范围内已有的数字进行赋值,如果超过范围则会new一个Integer重新进行赋值
- 例如
- ```
Integer i1=128;
Integer i2=128;
System.out.println(i1==i2);
```
- i1和i2已经超过了127的范围,所以这两个数字是被重新New出来的不同的地址,i1与i2的地址是不一样的,所以输出一个false
# 枚举类
- 含义:将变量一个一个列举出来
- 作用:提供变量让自己去选择
- 关键字:在类名前面的关键字是enum
#### 与其他类的区别:
- 枚举类默认继承Enum类,而不是默认继承Object类
- 使用enum定义的枚举类默认使用final修饰,不能被继承
- 构造器只能使用private修饰
- 枚举类的所有实例会被自动添加public static final修饰
#### 方法:
(1) int ordinal():返回枚举值在枚举类中的索引值(第一个枚举值索引为0)
(2) Enum[] values():返回一个包括当前Enum类所有实例的对象数组
(3) String name():返回此枚举实例的名称,这个名称就是定义枚举类时的所有枚举值之一。一般用
toString()。
(4) Enum valueOf(Class enumType,String name):返回指定枚举类中指定名称的枚举值。名称必
须与在该枚举类中声明枚举值时所用的标识符完全匹配。
(5) String toString():返回枚举常量的名称。
# 单例类
- 作用:这个类的对象只能被new一次
- 写单例类的代码:
- 声明一个当前的类对象,私有化
- 构造方法私有化
- 提供一个方法来做初始化
- 判断当前类对象==null,返回一个New
- 不是null,返回对象本身
- ```
private static Singleton singleton=null;
private Singleton(){
}
public static Singleton getIns(){
}
```
# 正则表达式
### 特殊字符
### 预定义字符
### 方括号表达式
### 花括号表达式
### 实例
1、验证用户名和密码:"[1]\w{5,15}$"、"[A-Za-z]_[0-9]"。由数字、字母、下划线组成,并且第一
个字必须为字母,长度为:5~15。
2、验证电话号码:"(\d{3,4}-)*\d{7,8}"正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx;
XXX-XXXXXXX XXX-XXXXXXXX XXXX-XXXXXXX XXXX-XXXXXXXX
3、验证身份证号(18位数字):"[1-9]\d{16}(\d
4、验证Email地址:^\w+(\w+)@\w+([-.]\w+).\w+([-.]\w+)*$;zhang_san@163.com
5、只能输入由数字和26个英文字母组成的字符串:[2]+$ 、[\w&&[_]]$”、[3]+ ([A-
z]+\d?)$
6、整数或者小数:[4]+.{0,1}[0-9]{0,2}$
7、只能输入数字:"[5]*$"
8、只能输入n位的数字:"^\d{n}$"
9、只能输入至少n位的数字:"^\d{n,}$"
10、只能输入m~n位的数字:"^\d{m,n}$"
11、只能输入零和非零开头的数字:"^(0
12、只能输入有两位小数的正实数:"[6]+(.[0-9]{2})?$"
13、只能输入有1~3位小数的正实数:"[7]+(.[0-9]{1,3})+$"
14、只能输入非零的正整数:"^+?[1-9]\d*$"
15、只能输入非零的负整数:"^-[1-9][0-9]*$”
16、只能输入长度为3的字符:"^.{3}$"
17、只能输入由26个英文字母组成的字符串:"[8]+$"
18、只能输入由26个大写英文字母组成的字符串:"[9]+$"
19、只能输入由26个小写英文字母组成的字符串:"[10]+$"
20、验证是否含有%&',;=?$"等字符:"[%&',;=?$\x22]+"
21、只能输入汉字:"[11]{0,}$"
22、验证URL:"^http://([\w-]+.)+[\w-]+(/[\w-./?%&=]*)?$"
23、验证一年的12个月:"^(0?[1-9]
24、验证一个月的31天:"^((0?[1-9])
25、获取日期正则表达式:\d{4}[年
### 用法:
- 步骤:
- 定义表达式
- 获得用户的输入
- 用这个表达式来校验用户输入是否合法
- 代码:
```
String exp="^\d{3}$";
String input="123";
System.out.println(input.matches(exp));
```
- 注:正则表达式开始必须用^    结尾必须用$    并且要注意转义字符
# 国际化
- 含义:程序在不同地区运行时,应动态的显示不同地区的语言
### 方法:
- 创建国际化的配置文件:
- 在要用到国际化的类文件src下,new一个properties 在Wizard方框内搜索files
- 文件名称有命名规范:
- baseName_language_country.properties(基本名+语言+国家)
- res_en_US.properties
- baseName_language.properties(基本名加语言)
- baseName.properties(只写基本名)
- 针对英国的配置文件:
- username=username
- pwd=password
- 注:
- 不需要加引号和分号结尾
- 创建针对中国的配置文件时,需要重新创建一个配置文件
- 在主页面中调用国际化配置文件时:
- ```
Locale locale=Locale.getDefault(); //得到当前电脑所处的语言环境
//如果选择其他国家的:
//Locale locale=Locale.US;
ResourceBundle bundle=ResourceBundle.getBundle("res",locale);
//程序加载所有"res"开头的配置文件,依据本地的语言环境选择哪个配置文件
System.out.println(bundle.getString("username"));
System.out.println(bundle.getString("pwd"));
```
# Scanner
- 键盘输入:
? Scanner scanner=new Scanner(System.in);
- 方法:
- int aa=scanner.nextInt(); 表示接收数字
- String aa=scanner.nextLine(); 表示接收字符串
- 等等等等...........
#### 需要注意的坑:
- 使用 String aa=scanner.next();一样可以接收字符串,但是它不会接收空格,只接收第一个空格之前的内容
- 在使用对应的方法时,如:sacnner.nextInt(); 只接收整数的部分,后面的符号、小数、字符串等不会被接收
- 如果在上一步接收时,输入了数字及回车,nextInt的部分只接收数字,回车会被下一行的nextLine();接收到,进行一次回车,所以在看到结果时相当于跳过了nextLine()的部分
- 针对上述问题,我们需要在接收完数字后,再进行一次接收字符串:sacnner.nextLine();
#### 用Scanner读取文件
- File file=new File(“d;/tiku.txt”);
- Scanner scanner=new Scanner(file);
需要抛出一个异常
#### Scanner中读取文件的方法:
- scanner.hasNext();检测下一行有没有内容
- scanner.nextLine();打印下一行的内容
# 剪切板Clipboard
调用剪切板的方法:
- Clipboard clipboard=Toolkit.getDefaultToolkit().getSystemClipboard();调用剪切板
- StringSelection selection=new StringSelection("6666");把想要让剪切板复制的话写进引号内
- clipboard.setContents(selection,null);把写出的话放进剪切板,set是设置,contents是内容
注:这三行的作用就是复制即ctrl+c的作用,用代码来完成复制
- Transferable transferable=clipboard.getContents(null);拿到剪切板里的内容   Get是得到, Contents是内容
- String search=(String) transferable.getTransferData(DataFlavor.stringFlavor);需要进行强制类型转换,并处理报错,因为剪切板可以复制很多类型的内容,比如图片,字符串,文件等等,所以需要设置拿到的是字符串格式。
注:这两步加起来才是拿到字符串的内容
- 上面两行是复制内容,下面两行是把内容取出来
#### 转义字符
# 内存分配
如:常用类中 int a=5;
?
?
- 栈内存
- Int a 会放在栈内存里
- Scanner scanner= 会放在栈内存
- int[] 会放在栈内存
- 堆内存
- new Scanner() 会放在堆内存
- new int[5] 会放在堆内存
- 常量池(方法区)
- 5会放在常量池内
创建对象时:分为三部分:
- 分配空间
- 对象初始化
- 分配地址
# 面向对象(思想)
### 权限修饰:
- public: 公开的,所有不同的包,不同的类全都可以访问得到。
- private: 私有的,只有自己的类(同一个class)中可以访问,其他的都访问不到。
- protected: 受保护的,除了不同包的其他类访问不到,其他都可以访问到,不同包的子类也可以 访问的到。
- 默认:只有同一个包中的类可以访问到,不同包访问不到。
### 封装:
- 实际含义是:该隐藏的隐藏,该暴露的暴露
- 全局变量:定义在类中的,所有方法都可以访问到,叫全局变量
- 局部变量:定义在一个方法里的,只有本方法可以访问的叫局部变量
##### 定义变量:
? 权限修饰符(public) + 类型(void、int、string、array[]...) + 变量名称
注:变量名称要用合法的JAVA标识符,首单词的第一个字母小写,后面的每一个单词首字母大写
##### 可变参数:
```
public static void test(int...a){
}
```
- 当不确定参数内要传多少个时,用int... 在调用test方法时,可以任意传几个参数,同时会把a当作数组进行处理
- 注:
- 如果一个参数里有可变参数,并且有多个参数,那么可变参数一定要放在最后一个
- ```
public static void test(int b,int...a){
}
```
##### 方法封装:
- -定义格式: 修饰符(private) + 返回值类型(void、int、string....) + 方法名(自定义)+
( 参数类型 参数名称 + , + 参数类型 参数名称) + { 代码体 + return 表达式 }
- 形式参数:在参数名称中,方法本身起的名字叫形式参数,只起一个代号的作用。
- 实际参数:在通过 . 调用方法时,依据形式参数传进的东西是实际参数。
- 不需要new对象就可以访问的方法封装:
?
? return new Person();
?
- 方法封装的好处:1.方便维护 2.减少冗余代码的出现
##### 构造方法:
- 作用:用于该类的实例对象的初始化
- 格式: public Person(){ }
- 示例: pubilc int size;
?
? size=18;
?
- 这就是给对象做了初始化,只要在另一个类中调用了Person的方法,new出了Person,那么当输出size时,默认输出18.
- 构造方法中也可以传参数,当传入了参数后,再调用此方法是就必须传进参数对应的类型,如果想既可以传参数,也可以不传参数,那么就再构造一个同名的方法,该方法不加任何参数,这就叫构造方法的重载
##### This关键字
- this关键字总是指向该方法的对象。
- 当this出现在构造方法中,this指的是该构造器正在初始化的对象,(也就是最外层的)
- 在普通方法中引用,this指的是调用该方法的对象
- 作用:this关键字最大的作用就是让类中一个方法,访问该类里的另一个方法或Field
##### 通过set方法对对象进行初始化:
代码: public void setSex(String sex){
?
?
##### 小结:
- 变量—————— 类对应的属性
- 构造方法——————new对象的时候对对象初始化
- 方法(函数)——————功能性的方法
##### 封装打包学生类的代码:
Demo demo=new Demo();
Student student=new Student("tom",18,6,"3333","男");
demo.save(student);
public void save(Student student){
?
?
}
##### 匿名对象
如上:Demo demo=new Demo();
?
- new Student只用到一次,没有给他起名字,这就是匿名对象
##### 值传递
- JAVA的参数传递方式只有一种,那就是值传递
- 值传递含义:就是将实际参数的复制品传进方法,也就是重新创建一个一模一样的参数,对这个复制品进行方法操作,而实际参数的本身并没有受到影响。
如:int a=5,b=5;
?
?
?
?
```
public void change(int a, int b){
public static void main(){
}
//打印后a的值依旧是10,调用方法并没有改变,因为传进去的是基本类型的副本,只有引用类型才会传进地址,最后的值会被改变,如果用change方法改变a的值的话,需要在后面return
```
传进的是引用类型时:
- ```
public void change(StringBuffer buffer){
public static void main(){
}
//此时打印后结果为ABC123,因为传进去的是地址,原本的值会被修改
```
在此次方法操作中,a和b的值依旧是5,并没有变成100,就是对a与b的复制品进行了操作,实际参数本身没有改变
如果想要将ab变成100的话,就需要返回a与b,在后面加return ,并将void改为Int
- 只有基本类型的值传递才是将复制品传进方法,其他类型的值传递是传进地址值的复制品,所以是可以对实际参数进行修改的
##### 重载
- 方法名不可以重名,但是方法名相同时,参数列表不同时,如:方法一有两个参数,方法二有三个参数,尽管两个方法名字相同,但是可以同时存在,这叫方法的重载
- 重载只与方法名和参数名称有关,与权限修饰符,返回值类型等无关
- 方法名相同,参数名称不同或参数数量不同时,才叫重载
##### 递归
- 含义:自己调用自己
- 斐波那契数列:
- 1 1 2 3 5 8 13 21 34
- 假设要求第n位的值:
public int fb(int n){
?
?
?
?
?
}
- 递归最重要的是找到第一个递归的出口
##### Static
- 特点:
- static是跟随类的出现而出现,类名出现一次,那么static后面的内容就会执行一次
- 被类的所有对象(new一次就是一个对象)共享:在调用static修饰的变量时,不同对象调用的是同一个变量,对象一对变量b进行改变时,对象二中的变量b也会改变而不同的对象调用不被static修饰的变量时,不同的对象使用的是不同的变量,对象一修改变量a时,对象二的变量a是不会被改变的
- 例如:
- ```
static int a=1;
public static void main(){
}
//此时打印的num2的a,它的值为2,因为两个对象共用的一个变量,num1做了修改,num2也会有改变
```
- 可以通过类名直接调用
- 注意事项
- 在静态方法中不可以使用this关键字
- 静态方法里不能访问成员变量或成员方法 因为静态方法是随着类的出现而出现,成员变量需要先New出对象,才能访问得到
- 静态变量和成员变量的区别
- 所属不同
- 静态变量属于类,所以也称为为类变量
成员变量属于对象,所以也称为实例变量(对象变量)
- 内存中位置不同
静态变量存储于方法区的静态区
成员变量存储于堆内存
- 内存出现时间不同
静态变量随着类的加载而加载,随着类的消失而消失
成员变量随着对象的创建而存在,随着对象的消失而消失
- 调用不同
静态变量可以通过类名调用,也可以通过对象调用
- 用武之地
- 使用工具方法时,可以加static,因为每次使用工具都需要New出对象,过于麻烦,而加上static后,只需要使用类的名字直接用点就可以调用,不需要new对象
- 只需加载或执行一次
##### 代码块:
- 局部代码块:
- 出现在方法的内部,用大括号括起来的就是局部代码块
- 定义在局部代码块内的变量,出了局部代码块后,外面的访问不到
- 限定变量生命周期,及早释放,提高内存利用率
- 构造代码块
- 在类中方法外出现;多个构造方法中相同的代码存放到一起,每次调用构造都执行时就可以用构造代码块,并且在构造方法前执行
- 运用:当所有的构造方法中都有相同的部分时,可以把他放进构造代码块里,这样可以减少构造方法中相同的部分出现
- 静态代码块
- 在构造代码块前加上static,构造代码块是New一次,代码块的内容出现一次,静态代码块是类出现一次,就执行一次
# 集合框架
#### 集合和数组的区别:
- 长度
- 数组的长度固定
- 集合长度可变
- 内容
- 数组存储同一类型元素
- 集合存储不同类型元素
- 元素类型
- 数组可以存基本类型,可以存引用类型
- 集合只可以存引用类型
image-20210713105709954
### For Each循环
- 与For循环的区别: for循环需要通过下标一个一个去找,而foreach是直接遍历每一个对象
```
UserTable user=new USerTable("tom",19);
UserTable user1=new USerTable("jack",18);
UserTable user2=new USerTable("Amy",17);
ArrayList list=new ArrayList<>();
list.add(user);
list.add(user1);
list.add(user2);
for(UserTable user:list){
}
```
- 注:
- 循环前先判断集合是否为null,如果为Null会直接报空指针异常。
- foreqch遍历,只可以遍历数组或者Collection,是不可以遍历map的
### Collection
- 是一个接口并不是一个类,所以不可以被实例化。
- collection也可以有多态,可以通过Collection类型new出一个实例,如Collection collection=new ArrayList();
注:当传进的参数类型是Object时,代表可以传任何类型的参数,因为Object是所有类型的父类
- collection是自动补全toString方法,是可以直接打印出元素的,而数组直接打印的话是打印地址
- 方法:
- 1:添加功能
boolean add(Object obj):添加一个元素
boolean addAll(Collection c):添加一个集合的元素
- 2:删除功能
void clear():移除所有元素
boolean remove(Object o):移除一个元素
boolean removeAll(Collection c):移除一个集合的元素
- 3:判断功能
boolean contains(Object o):判断集合中是否包含指定的元素
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素
boolean isEmpty():判断集合是否为空
- 5:长度功能
int size():元素的个数
- 6:交集功能
boolean retainAll(Collection c):两个集合都有的元素
collection.retainAll(c2);
这个功能意思是   把c2和collection的交集重新赋值给了collection,返回值类型的布尔值代表collection是否被改变过
- 7:把集合转换为数组
String[] array=(String[]) collection.toArray();
数组转集合:Arrays.asList(array);
#### 4:获取功能
- Iterator iterator()(重点)
Iterator iterator=collection.iterator(); (代表获得当前集合的迭代器)
while(iterator.hasnext()){
System.out.println(iterator.next());
}
#### 越界报错:
- 注:该过程中需要注意,多输出一个iterator,next(),表示找的是下一个元素
- 注意的报错:NoSuchElementException与数组的越界报错一样,都表示访问的东西不存在
- ```
Student s1 = new Student();
s1.setname("Tom");
s1.setage(18);
Student s2 = new Student();
s2.setname("jack");
s2.setage(20);
collection.add(s1);
collection.add(s2);
Iterator iterator=collection.iterator();
while(iterator.hasNext()){
```
```
注:上面的代码中,第一行打印的是Tom的名字,第二行打印的是Jack的年龄,因为使用了两次hasNext(); 第二个hasNext();找的是第二个元素Jack,所以打印了Jack的年龄
```
#### 迭代器的遍历方法:
- 使用for循环使用迭代器遍历集合:
- for(;iterator.hasnext()??{
System.out.println();
}
### List
- List是Collection接口的一个子接口。
- List是一个有序的集合,允许重复的元素存在
##### 方法:
- List继承Collection,所以Collection有的方法,List也有
- void add(int index,Object element):在指定位置添加元素
- List可以通过Get方法,利用下标获得元素,而collection没有Get方法,所以只能通过迭代器获得元素
- List也有迭代器
- iterator.nextIndex(); 返回下一个索引
- interator,previousIndex(); 返回上一个索引
- interator.hasPervious(); 有没有前一个元素
```
ListIterator iterator=list.listIterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
```
- 删除功能,根据索引删除元素,返回的是被删除的元素
- System.out.println(list.remove(1));
- 修改功能,根据索引修改元素,返回被修改的原来的值
- System.out.println(list,set(2,"mmm"));
把下标为2的元素bbb修改为mmm,则返回bbb。
##### ArrayList:
- ArrayList的底层是数组,特点是查询快,增删慢
- 线程不安全,效率高。
##### Vector:
- 底层数据结构是数组,查询快,增删慢。
- 线程安全,效率低。
##### LinkList:
- LinkList的底层是链表,特点是查询慢,增删块
- 线程不安全,效率高。
- 方法:
- LinkedList list=new LinkedList();
list.addFirst(); (在第一位添加元素)
list.addLast(); (在最后一位添加元素)
list.getFirst(); (获得第一位)
list.indexOf(); (获得元素的索引)
list.lastIndexOf(); (获得最后的索引位置)
list.removeFirst(); (移除第一个)
##### 注:
容器指集合
### ConcurrentModificationException
- 含义:并发修改异常
- 并发:
- 该报错会在迭代器里出现
- 假如List中有三个元素,删除第三个元素,就会并发修改异常报错
- 因为,迭代器是根据原本有三个元素的List拿到的,本身是准备遍历三个元素的,但是中途删除了一个元素,两边数据不一致,同时更改了一个数据,所以才是并发修改异常
```
ListIterator iterator=list.listIterator();
while(iterator.hasNext()){
```
### Set
- 与List的区别:
- List有序,允许重复的值存在
- Set无序,不允许重复的值存在
##### 方法:
- Set是Collection的子类,所以也拥有Collection所有的方法
##### HashSet:
- Set的实际类只有HashSet,所以HashSet的方法都是Collection的方法
- HashSet的遍历方法:
- 使用迭代器
- 使用for each遍历
- 因为没有下标,所以不可以用for循环遍历
- 特性:
- 不保证顺序
- 底层数据结构是哈希表
- 哈希表指数组加链表的数据结构
- 哈希表:当a元素占用了数组的3位置后,另一个b元素经过哈希值的运算后得出也要占用3位置,这时就用链表的箭头从a元素指向b元素
##### linkedhashset
- 底层是哈希表加链表
- 哈希表保证唯一性,链表保证有序
##### treeset
- 可以排序
- 使用元素自然排序排序
- 使用Comparator
##### 注:::::
- HashSet的底层是HashMap:
- HashSet中的add方法调用的其实是HashMap中的put方法
- LinkedHashSet的底层是LinkedHashMap
- TreeSet的底层是TreeMap
- 总结:Set其实就是Map的一部分,将Map的键抽出来就是Set
### List和Set的使用场景区别
当想要添加的元素不能重复时,或者只想看最终结果都有哪些。就将元素添加在set里,否则一般情况用List
### Collections
- Collection与Collections的区别
- Collection 是单列集合的顶层接口(总的一个接口),有子接口List、Set。属于抽象类,是不能被实例化的
- Collections 是针对集合进行操作的工具类,有对集合进行排序和二分查找的方法,都是静态方法,通过类名直接调用
##### 方法:
- 排序方法:默认情况下是从小到大
- Collections.sort();
- ```
List list=new ArrayList<>();
list.add(5);
list.add(2);
list.add(6);
list.add(9);
Collections.sort(list);
System.out.println(list);
```
- 二分查找:
- Collections.binarySearch(List<?>list,T key )
- 传进两个参数,一个列表一个元素,查找该列表内某一个元素出现在哪一个位置
- 返回的是索引
- 列表内的元素必须是有序的
- 获取最大值:
- Collections.max(Collection<?> coll); 参数传集合
- Collections.min();
- 反转:
- Collections.reverse(List<?> list); 参数传列表
- 并不是将列表里的元素排序,只是将顺序反转
- 随机置换:
- Collections.shuffle(List<?> list); 参数传列表
- 将列表内元素的顺序打乱
### Map
- Map与Collection是两个独立的体系
- Map与Collection的区别:
- map存储元素是成对出现的,是键值对的一个体系,键是唯一的,值是可重复的
- 键值对的含义是,可以给值起名字
- Collection元素是单独的
- map集合的数据结构是哈希表(哈希表就是不重复),这个数据结构只针对键有效,和值无关
- 意思为,键是唯一的,不可重复,值可以重复
- 键可以为null, 但是只可以有一个null键,因为键具有唯一性
- 代码例子:
- ```
HashMap map=new HashMap<>();
map.put("aaa","5");
```
#### HashMap:
##### 方法:
- 添加功能:
- map.put(key,value) k写键的名称,value写赋的值
- 另一个功能就是可以返回:
- 如果是第一次存储的话,存储元素后,返回Null
- 如果不是第一次存储的话,就用现在的值把以前的值替换掉,并返回以前的值
- 获取功能:
- map.get(k); k写键的名称,通过get键,从而获得键对应的值
- map.entrySet(); 得到的是键值对的一个集合
- 该方法也可以被接收后返回: Set> kv=map.entrySet();
- 因为返回的是一个集合,所以用set类型接收,泛型里面填Entry<>
- 在遍历Kv时,也是用遍历Set类型的方法遍历(迭代器或者for each)
- ```
Set> kv=map.entrySet();
Iterator> iterator=kv.iterator();
while(itreatro.hasNext()){
}
```
- map.keySet(); 获取集合中所有键的集合 这个集合用Set接收,因为键不可以重复
- map.values(); 获取集合中所有值的集合 接收这个集合时,用collection接收  , 不能用Set, 因为值是可以重复的,用了Set后值就不可以重复
- 删除功能:
- map.clear(); 移除所有键值对元素
- map.remove(k); k写键的名称,根据键删除键值对元素,并把值返回
- 判断功能:
- map.containsKey(k); 判断集合是否包含指定的键
- map.containsValue(value); 判断集合是否包含指定的值
- map.isEmpty(); 判断集合是否为空
##### HashMap与Hashtable的区别:
- map线程不安全,效率高
- table线程安全,效率低
#### LinkedHashMap:
- Map接口的哈希表和链接列表实现,具有可预知的迭代顺序
#### TreeMap:
- 键是红黑树结构,可以保证键的排序和唯一性
### 无限嵌套的补充:
- list set map 都是可以循环无限嵌套的
- ```
List list=new ArrayList<>();
list.add(usertable);
List> school=new ArrayList<>();
school.add(List);
```
- 一个集合嵌套一个集合时,注意泛型要填第一个集合的类型。
- ```
Person s1=new Person("tom",18);
Person s2=new Person("tom",18);
Person s3=new Person("jack",20);
HashSet set=new HashSet();
set.add(s1);
set.add(s2);
set.add(s3);
System.out.println(set);
```
- 此时打印set,是会将所有对象都打印出来,虽然两个都是tom,18岁,但是在set内添加的是s1和s2两个不同的对象,两个对象都是New出来的,与对象里面的内容是否相同无关,所以两个tom都是可以打印的
### 数据结构:
#### 数组:
- 定义:相同数据类型的元素按一定顺序排列的集合。
- 连续的存储空间 特点:查询快,但是增删慢
- 如果需要增加或删除的话,就是重新开辟空间,创建另一个数组,把原本的填上去再加上需要增加的元素,删除反之
- 时间复杂度:O(1)
#### 链表:
- 链表中每个元素都是一个对象,每个对象称为一个节点,包含有数据域key和指向下一节点的指针next,通过各个节点间的相互连接,最终串联成一个链表
- 通常链表每一个元素都要保存一个指向下一个元素的指针
- 不是连续的存储空间,用箭头一个一个指向下一个元素 特点:查询慢,增删块
- 时间复杂度:O(n)
#### 队列:
- 含义:程序运行多个任务,但是一次处理不过来,把所有的任务依次放进队列,一个一个去取
- 特点:先进先出
#### 栈:
- 定义:限定仅在表尾进行插入和删除操作的线性表
- 含义:好像进电梯,入口和出口是同一个,先进来的排在最后面,最后进来的排在最前面
- 特点:后进先出,先进后出
#### 树:
- 定义:树是n(n>=0)个结点的有限集。n=0时称为空树。在任意一颗非空树中:
- 有且仅有一个特定的,称为根的结点
- 当n>1时,其余结点可分为m(m>0)个互不相交的有限集t1、t2、.......tm,其中每一个集合本身又是一颗树,并且称为根的子树。
- 一对多的层级关系
- 表示人物职称或者级别时,用树状图
- 二叉树:一个元素只能分两个叉
- 左边的放小的,右边的放大的
- 如果从左往右数,那么就是依次从小到大排列
##### 遍历方法:
二叉树的遍历是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次
- 前序遍历
- 若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。
- 中序遍历
- 若树为空,则空操作返回,否则从根结点开始(并不是先访问根结点),中序遍历根结点最左侧的左子树,然后访问根结点,最后中序遍历右子树。
- 后序遍历
- 若树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。
- 层序遍历
- 若树为空,则空操作返回,否则从树的第一层,也就是根结点开始访问,从上到下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。
- 注:区分前序遍历和层序遍历:前序为先遍历左边,左边的全部找完再遍历右边,层序为按照层级关系,先遍历上层,按照层级顺序,一层一层找
#### 堆:
- 含义:堆是具有下列性质的完全二叉树:
- 每个结点的值都大于或等于其左右孩子的结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
- 在一个堆中,根结点一定是堆中最大(小)的结点。较大(小)的结点靠近根结点
#### 图:
- 定义:图是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合
- 在图形构造中,顶点之间的关系可以是任意的,图中任意两个数据元素之间都可能相关。
- 表示人物关系
- JAVA的垃圾自动回收就是图的应用,如果某个对象正在被其他对象用着,那么就不是垃圾。如果某个对象失效,或者内容为null,那么图中的连线或者节点就会消失,JAVA判定为垃圾
##### 遍历方法:
- 深度优先遍历:
- 查找所有的顶点并标记,在没有碰到重复顶点的情况下,始终查找右边的顶点,在没有通道可走的情况下,原路返回,找寻没有被标记的顶点,最终返回到起点,遍历结束,该遍历方法本质是一个递归的过程
#### 时间复杂度
- O(1) 表示需要查找一次就可以找到需要查找的元素
- O(n) 表示要查找第几个,就需要查找第几次,查找第N个,就需要查找第N次
# 封装业务层:MVC三层架构
M:model(模型),指实体类
V:view(视图),能看到的所有东西就是视图
C:controller(终端控制器)
前端的任何请求,都要转到后台的代码控制器,控制器拿到数据后,再交给业务层的方法,做业务处理,业务层拿到东西后再去调动数据库
- 控制层: 接收或者返回数据/前后端的连接
- 服务层:做具体的业务处理
- 数据库层:做增删改查操作
例如:普通的代码页面中的命令行就是视图,然后选择的1.2.3接收给控制层,控制层接收数据给服务层,服务层拿到数据做具体的业务处理,服务层接收用户的输入,然后把他封装成一个对象,再传给数据库,数据库做增删改查。
# JDBC
- 全称: java database connection
#### 配置四大参数,用于获得mysql链接
- 用户名、密码
- url(地址)(指链接谁、链接哪个IP下,哪个端口下的哪个数据库)
- 驱动
```
//加载驱动
Class.forName("com.mysql.jdbc.Driver") //引号内为驱动名称
//填写url,用户名,密码获得链接
Connection connection= DriveManager.getConnection("jdbc:mysql://127.0.0.1:3306/库名?useUnicode=true&characterEncoding=utf-8","root","root123") //如果connection没有打印null打印出地址,表示链接成功
```
注:乱码时,在填写url时加上      ?useUnicode=true&characterEncoding=utf-8
#### 增删改查的语句
- 构造sql语句
- 获得执行sql的对象(根据connection获得statement)
- 往sql里赋值
- 执行
```
String sql="insert into book_table(book_name,book_author,book_price) values(?,?,?)"; //定义sql语句
PreparedStatement statement=(PreparedStatement)connection.prepareStatement(sql);
statement.setString(1,"三国");
statement.setString(2,"某某某");
statement.setLong(3,500); //数字表示第几个问号
statement.executeUpdate(); //执行更新操作
//int result=statement.executeUpdate(); 返回数字表示影响了几行
```
注:直接使用Statement对象执行sql语句,拼接字符串时,会有sql注入攻击的安全隐患
如:select*from user_table where user_name='tom' and user_pwd='456' or 1=1;
- 删除
```
String sql="delete from book_table where book_id=?";
```
- 更改
```
String sql="update book_table set book_name=? where book_id=?";
```
- 查询
```
String sql="select * from book_table where book_name=? and book_price=?";
PreparedStatement statement=(PreparedStatement)connnection.preparedStatement(sql);
statement.setString(1,"三国");
statement.setInt(2,200);
Resultset set=statement.executeQuery();
while(set.next()){
}
```
# IO流
## File
- File包含视频、图片、音频等,也包括文件夹
### 访问文件的相关方法:
- File file=new File("d:/text/aaa.txt");
- File file=new File(String,File);
- 前一个表示文件的父目录(上级目录),后一个才是该文件
- 前后两个参数都可以传String或者File,都表示前一个是上级目录,后一个是该文件名
- file.getName(); 返回文件名
- file.getPath(); 返回该文件的路径名(不常用)
- file.getAbsoluteFile(); 返回该文件的绝对路径(用这个)
- file.getParents(); 返回该文件的对应目录的父目录(也就是上级目录)
- file.renameTo(); 重命名此文件,成功则返回true,否则返回false
- 注:重命名时,括号内重新写上新的New File,要把重命名好的文件的路径写上,否则默认删除原文件,在当前目录重新创建该文件并重命名(该方法与剪切相同)
- file.lastModified(); 返回文件的最后修改时间,返回毫秒值
- file.length(); 返回文件的长度,返回的是多少字节
- file.getFreeSpace(); 得到当前盘剩余多少空间,返回的是字节
- file.getTotalSpace(); 返回当前盘总共有多少空间
### 文件检测相关的方法:
- file.exists(); 判断该文件是否存在
- file.canWrite(); 判断该文件是否可写
- file.canRead(); 判断该文件是否可读
- file.canExecute(); 判断该文件是否可执行
- file.isFile(); 判断该文件是否是文件,而不是文件夹
- file.isDirectory(); 判断该对象是否是目录
- file.isAbsolute(); 判断该文件的路径是否是绝对路径
- file.isHidden(); 判断该文件是否是隐藏的
### 文件操作的方法:
- file.createNewFile(); 当文件不存在时,创建一个该File对象所对应的文件,创建成功返回true,否则false
- file.delete(); 删除该File对象
- 注:使用该方法时,当删除的是一个文件夹且文件夹有内容时,文件夹不会被删除,如果是个空文件夹则可以删除成功
- file.mkdir(); 在指定目录下创建该文件夹
- 注:如果要创建层层嵌套的多个文件夹需要用.mkdirs();
- file.mkdirs(); 创建该对象路径中的所有目录,如果上级目录不存在,会同时将上级目录创建出来
- file.listFile(); 列出File对象的所有子文件和路径,返回File数组
- 注:返回的对象需要用数组去接收,然后再遍历数组输出
- 该方法只会找出File对象内的文件,不会再找出文件夹内包含的所有内容,如果要再往下一层一层查找所有,需要用到递归
- 递归方法:
- ```
public static void getFiles(File file){
}
```
- file.listRoots(); 找到有几个盘,返回的也是数组
- 查看盘服的大小容量:
- ```
File[] roots=File.listRoots();
for(File root:roots){
}
```
## io
### 分类:
- 按照数据流向:
- 输入流(FileInputStream):读入数据
- 输出流(FileOutputStream):写出数据
- 按照数据类型:
- 字节流
- 字节流可以处理任何东西,文字照片视频。用不了字符流就用字节流
- 抽象基类(基类就是父类):InputStream OutputStream
- 用的时候用子类:FileInputStream FileOutputStream
- 字符流
- 如果数据所在的文件通过windows自带的记事本打开并能看得懂里面的内容,就用字符流
- 抽象基类(父类):Reader Writer
- 子类:FileReader FileWriter
## FileOutputStream
### 构造方法
- FileOutputStream stream=new FileOutputStream(String);
- 构造参数可以再加一个boolean,代表内容不会替换,接着原本的内容追加去写
- 参数String写路径的时候可以加上不存在的文件名或路径,会在新创建的文件内写内容
### 方法:
- stream.write(); 写出
- 参数可以传int
- 传进的int数字,按照ASCII表被转换成了字符
- 传byte[]
- byte[]   bytes={98,99,62};   一样打印的是字符
- 传(byte[],int off,int len)
- 两个int,前一个Int代表从哪个索引开始传,后一个int代表传几个元素
- 想要直接传字符进去:
- stream.write("hello".getBytes());
- 将字符串转为字节数组
- stream.write("\r\n".getBytes());
- 后面追加的内容进行换行
- 在windows系统内换行是\r\n
- linux:\n
- mac:\r
- stream.close(); 关闭IO流
## FileInputStream
### 构造方法:
- FileInputStream stream=new FileInputStream();
- 参数只可以传String或者File(也就是文件的路径),不能加boolean
### 方法:
- stream.read(); 读入
- 读入方法是有返回值的,返回值类型是Int,代表读到的字符所对应的ASCII表的数字
- stream.read();参数内什么都不传,代表只读一个字符,返回该字符在ASCII表对应的数字
- ```
int result=stream.read();
System.out.println((char)result);
```
- 因为返回的是数字,所以要将数字进行强制类型转换,在前面加(char)
- 注:如果读不到字符时,返回的数字是-1
- 用stream.read(); 一个一个字符去读一段话时,用循环来做
- ```
int by=stream.read(); //用来接收读到的每一个字符对应的数字
while(by!=-1){ //读到的数字不等于-1代表读到了字符内容
}
inputStream.close();
```
- 缩减改进后:
- ```
int by=0;
while((by=stream.read())!=-1){
}
inputStream.close();
```
### 字符流读入内容:
- stream.read(byte[]);
- 传进一个字节数组,在该数组用动态初始化规定范围后,读入的就是文章中规定范围个数的字节数,读到后,把读入的内容放进字节数组中
- ```
byte[] bytes=new byte[1024]; //动态初始化字节数组的范围,读入字节的最大范围就是规定的这个数字
int len=0; //字节数组的长度,也就是读到了多少个字节
while((len=stream.read(bytes))!=-1){ //在读到了字节后,长度一定是大于-1
}
stream.close();
```
- 注:加上0和len的目的是防止字符数组容量过大,实际读到的内容只有一点,但是在每次转换为字符串时,字符数组中的空余内容都会被转换一次,效率低
- 注2:在规定字节数组的容量时,注意编码格式,GBK内的一个中文字符表示两个字节,如果规定的的字节数组范围是单数时,就会有一个字符只读了一半,所以规定范围时,一定是编码格式字节数的倍数
### 输入流和输出流的结合:
- ```
FileInputStream stream=new FileInputStream("d:/111.txt");
FileOutputStream stream2=new FileOutputStream("d:/222.txt");
byte[] bytes=new byte[1024];
int len=0;
while((len=stream.read(bytes))!=-1){
}
stream.close();
stream2.close();
```
## BufferedInputStream
- BufferedInputStream buf=new BufferedInputStream(new FileInputStream(d:/222.txt));
- 参数内传一个输入流
### 方法:
?

  1. a-zA-Z ??

  2. A-Za-z0-9 ??

  3. A-z\d ??

  4. 0-9 ??

  5. 0-9 ??

  6. 1-9 ??

  7. 0-9 ??

  8. A-z ??

  9. A-Z ??

  10. a-z ??

  11. \u4e00-\u9fa5 ??

相关