idea技巧:
alt+/ 代码自动补全
自动补齐main 输入main 回车
自动补充输出语句 输入sout 回车
单行注释和取消 ctrl + /
多行注释 ctrl + shift +/
取消多行注释 ctrl + shift +\
自动导入包 ctrl+shift+o
自动添加构造函数和生成函数等 alt+ins
自动重写抽象函数: 点击抽象类,alt+enter
将一段代码生成一个函数 ctrl+alt+m
选中多个相同的值 shift + f6
当遇到代码量比较大时 ALT+7或者CTRL+F12 可以查看视图
当需要生成左边的定义内容的时候 使用 : CTRL+alt+v
效果:hm.entrySet() 按CTRL+alt+v
生成:Set<Map.Entry<String, Integer>> entries = hm.entrySet();
键盘录入
键盘录入的各种情况:
第一套体系:遇到空格,制表符,回车就会停止接受,这些符号后面的不会接收。
nextInt();接收整数
nextDouble();接收小数
next();接收字符串;
第二套体系:
nextline();接受字符串
package com.sxt;
import java.util.Scanner;
public class Hello {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
System.out.println(i);
}
}
随机数
导入包 import java.util.Random
Random r = new Random();
int number = r.nextInt(随机数的范围);
随机数的范围 bound 10(表示0~9)
要生成7~ 15 可以用 (bound 9)+7来实现
数组
静态初始化:
int [] array= new int[]{11,12,13};
求数组的长度 : 数组名.length
快速遍历数组 : 输入数组名.fori,然后直接回车。
动态初始化:数据类型[] 数组名 = new 数据类型[数组长度]
方法
方法:
最简单定义: public static void 方法名(){
方法体
}
带参数的方法定义: public static void method(int num1,int num2){
int result = num1 + num2;
System.out.println(result);
}
调用的时候直接method(10,20);
形参和实参:
形参:形式参数,是指方法定义中的参数
实参:实际参数,是方法调用时用的参数
带返回值的方法定义
public static 返回值类型 方法名(参数){
方法体;
return 返回值;
}
方法的重载:在同一个类中,定义多个同名方法,这些同名方法有同种功能。
同一个类中,方法名相同,参数不同的方法。且与返回值无关。
参数不同:个数不同,类型不同,顺序不同。
面向对象
设计对象并使用:
类和对象。类:是对象的共同特征。对象:是真实存在的东西。
类中的东西:
1 成员变量(属性,一般是名词)
2 成员方法(行为,一般是动词)
3 构造器
4 代码块
5 内部类
如何得到类的对象:
类名 对象名 = new 类名();
例如:Phone p = new Phone();
使用对象:
对象名.变量;
对象名.方法;
注意:类名的首字母建议大写,英文,有意义,满足驼峰模式,不能使用关键字,满足标识符规定。
public只能由一个,且于java文件名相同。
封装
封装:如何正确的设置对象的属性和方法。
重要原则:对象代表什么,就得封装对应的数据,并提供数据对应的行为。
private:
可修饰成员变量和成员方法;
被private修饰的成员只能在本类中才能被访问。
idea快速添加赋值函数和返回函数的快捷键:
是alt+fn+insert
ctrl+p快捷键是快速传参数。
%s 占位符
字符串
StringBuilder可以看成一个容器,创建之后里面的内容是可变的
可以提高字符串的操作效率。
构造方法:
常用方法:
更快更方便的方法:StringJoiner
构造方法:
示例:
成员方法:
集合
集合的定义:
ArrayList<String> list = new Arraylist<>();
成员函数:
但是集合中不能添加基本数据类型,所以当要添加基本数据类型的时候,我们需要改一下格式:
< >里面换成后面的东西,
<>里面也可以是自己定义的类
面向对象进阶
static
被static修饰的成员变量,叫做静态变量。
特点:被该类所有对象共享,静态变量是随着类的加载而加载的,优先于对象出现的。
调用方式:
1、类名调用。类如学生的老师都是同一个,则类Student.teacherName = "李老师"
2、对象名调用
被static修饰的成员方法叫做静态方法调用方式相同。
静态方法中只能访问静态,非静态方法可以访问所有,静态方法中没有this关键字
类别:
工具类:(1)类名见名知意 (2)私有化构造方法 (3)方法定义为静态方便调用。
继承
继承代码:public class 子类 extends 父类 {}
父类的构造方法不能被子类继承。
继承中 成员变量 的访问特点:就近原则(谁离我近,我就用谁)public class 成员变量继承特点 { public static void main(String[] args) { zi z = new zi(); z.show(); } } class Fu{ String name = "fu"; String hobby = "喝茶"; } class zi extends Fu{ String name = "zi"; String game = "cf"; public void show(){ //打印zi,其中this代表的是子类 System.out.println(this.name); //打印Fu,super代表的是父类 System.out.println(super.name); //打印喝茶 System.out.println(hobby); //打印cf System.out.println(game); } }
成员方法的访问特点:也是就近原则或者用this访问子类,super访问父类。
当父类的成员方法不能满足子类的需求的时候,可以进行方法重写。重写的方法后面要加上@Override,用来校验子类重写时语法是否正确。(加上之后,如果有红波浪线,表示语法错误)
构造方法的访问特点:1、父类中的构造方法不会被子类继承。
2、子类中所有的构造方法默认先访问父类中的无参构造,再执行自己。
调用父类的构造方法:
1、对于无参构造方法,可不写,系统自动填充
2、对于有参构造方法,必须手动写super()进行调用
this和super
this:理解为一个变量,表示当前方法调用者的地址值
super:代表父类存储空间
多态
多态是同种类型的对象,表现出的不同形态。
表现形式: 父类类型 对象名称 = 子类对象;
前提:(1)有继承关系 (2)有父类引用指向子类对象 (3)有方法重写
多态调用成员的特点:变量调用:编译看左边,运行也看左边
方法调用:编译看左边,运行看右边
package 多态; public class 调用成员特点 { public static void main(String[] args) { //创建对象 Animal a = new Dog(); //调用成员变量:编译看左边,运行也看左边 //编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有则编译成功,如果没有编译失败 //运行也看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值. System.out.println(a.name); //输出结果为 动物 //方法调用:编译看左边,运行看右边 a.show(); //输出的是Dog-show //整体的理解:现在是用a去调用变量和方法,而a是Animal类型的,所以默认会从Animal这个类去找 //成员变量:再子类的对象中,会把父类的成员变量也继承下的。 //成员方法:如果子类对方法进行了重写,那么在虚方法表中是会把父类的方法进行覆盖的 } } class Animal{ String name = "动物"; public void show(){ System.out.println("Animal-show"); } } class Dog extends Animal{ String name = "狗"; @Override public void show(){ System.out.println("Dog-show"); } } class Cat extends Animal{ String name = "猫"; @Override public void show(){ System.out.println("cat-show"); } }
但是多态也有弊端,不能调用子类新加的特有功能。
解决方法:将其在变回子类
判断a是否是Dog,如果是就完成一个强制转化: a instanceof Dog d
包
包名的规则:公司域名反写+包的作用
自动导包:alt+enter
java.lang包中:(1)String
final
用final修饰之后:
(1)表明该方法时最终方法,不能被重写
(2)表明该类时最终类,不能被继承
(3)表明时常量,只能被赋值一次。常量的命名规则(单个单词:全部大写;多个单词:全部大写,单词之间用下划线隔开)
(4)当final修饰的变量时基本类型,那么变量存储的数据值不能发生改变。当修饰的变量时引用类型:那么变量存储的地址值不能发生改变,对象内部的可以改变。
抽象类
抽象方法:将共性的行为(方法)抽取到父类之后。由于每一个子类执行的内容是不一样的,所以在父类中不能确定具体的方法体,该方法就可以定义为抽象方法。
抽象类:包含抽象方法的类
抽象方法定义格式:
public abstract 返回值类型 方法名(参数列表);
抽象类的定义格式:
public abstract class 类名{}
注意事项:1、抽象类不能实例化、
2、抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类
3、可以有构造方法
4、抽象类的子类 要么重写抽象类中所有的抽象方法,要么是抽象类
5、在重写抽象方法的时候,可以直接点击extends后面的类名然后alt+enter快捷操作。
接口
接口就是一种规则,是对行为的抽象。
接口的定义: public interface 接口名 {}
接口不能实例化
接口和类之间是实现关系,通过implements关键词表示
public class 类名 implements 接口名 {}
接口的子类(实现类):要么重写接口中的所有抽象方法,要么是抽象类
接口和接口之间的可以是单继承也可以是多继承。
注意:
(1)接口和类的实现关系,可以单实现,也可以多实现
public class 类名 implements 接口名1,接口名2 {}
(2)实现类还可以在继承一个类的同时实现多个接口。
public class 类名 extends 父类 implements 接口名1,接口名2 {}
接口中成员的特点:(1)成员变量:只能是常量 默认修饰符:public static final
(2)构造方法:没有
(3)成员方法:只能是抽象方法 默认修饰符:public abstract
jdk7以前:接口只能定义抽象方法。jdk8的新特性:接口中可以定义有方法体的方法。(默认,静态)
jdk9的新特性:接口中可以定义私有方法。
内部类
类中再定义类就是内部类,内部类表示的事物是外部类的一部分,内部类单独出现没有任何意义。
内部类访问特点:(1)内部类可以直接访问外部类的成员,包括私有(2)外部类要访问内部类的成员必须创建对象。
内部类的分类:(1)成员内部类(2)静态内部类(3)局部内部类(4)匿名内部类
成员内部类
成员内部类:写在成员位置的,属于外部类的成员。可以被修饰符修饰
获取成员内部类对象:
方法一:在外部类中编写方法,对外提供内部类的对象
方法二:直接创建格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
静态内部类
成员内部类的特殊情况,在其前面加上static。
静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象。
创建静态内部类对象的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
调用非静态方法的格式:先创建对象,用对象调用、
调用静态方法的格式:外部类名.内部类名.方法名();
局部内部类
1、将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量
2、外界是无法直接使用的,需要在方法内部创建对象并使用。
3、该类可以直接访问外部类的成员,也可以访问方法内的局部变量。
匿名内部类
匿名内部类的本质就是隐藏了名字的内部类。
格式:
new 类名或接口名() {
重写方法;
};
GUI
GUI(graphical user interface)又称图形用户接口,是指采用图形化的方式显示操作界面。
事件
事件是可以被组件识别的操作,当你对组件干了什么事情之后,就会执行对应的代码。
事件源:按钮,图片,窗体....
事件:某些操作,如鼠标单击,鼠标划入
绑定监听:当事件源发生了某个事件,则会执行某段代码。如键盘监听:lol中的tap键,
鼠标监听:lol打问号,动作监听:监听鼠标点击或键盘空格
java中的路径
绝对路径:一定是从盘符开始的
相对路径:不是从盘符开始的,而是从当前项目开始的。
常用API
Math
常用方法:
System
System是一个工具类,提供了一些与系统相关的方法
Runtime
Runtime表示当前虚拟机的运行环境。是动态的。
获取Runtime对象:
Runtime r1 = Runtime.getRuntime(); //因为Runtime类中是私有的构造方法。
Object和Objects
Object是java中的顶级父类。其只有无参的构造方法。
目前三个常见的:
克隆对象:
细节:方法在底层会帮我们创建一个对象,并把原对象中的数据拷贝过去
书写细节:1、重写Object中的clone方法
2、让JavaBean类实现Cloneable接口
3、创建原对象并调用clone就可以了
浅克隆:不管对象内部的属性是基本数据类型还是引用数据类型,都完全拷贝过来
深克隆:基础数据类型拷贝过来,字符串复用,引用数据类型会重新创建新的
BigInteger(大整数)
构造方法:
1、第二个方法和第四个方法类似,但是第四个方法是静态方法,范围是long的范围,且对-16~16进行了优化。而第二种方法则是无限大的整数。
2、对象一旦创建,内部记录的值不能发生变化
3、只要进行计算都会产生一个新的BigInteger对象
成员方法:
BigDecimal(大小数)
作用:(1)用于小数的精确计算。(2)用来表示很大的小数
创建对象方法:(1)通过传递都变了double类型的小数来创建对象
(2)通过传递字符串类型的小数来创建对象。
(3)静态方法获取BigDecimal对象:
public static BigDecimal valueOf(double val)
细节:(1)如果表示的数字不大,没有超出double的范围,建议使用静态方法
(2)如果表示的数字比较大,超出了double的范围,建议使用构造方法
(3)如果我们传递的是0~10之间的整数,包含0,10,那么方法会返回已经创建好的对象,不会重新new
devide的舍入模式:(1)up:远离0方向舍入的舍入模式
(2)DOWN:向0方向舍入的舍入模式
(3)GEILING:向正无限大方向舍入的舍入模式
(4)FLOOR:向负无限大方向舍入的舍入模式
正则
设qq是一个字符串
qq.startWith("0") //表示0在开头
qq.charAt("i") //表示返回 i 的索引
"a".matches("\\d") // \\d只能是任意的一个数字,两个\\表示一个\,第一个\表示的是转义字符。
爬虫
两个类:
(1)Pattern:表示正则表达式
(2)Matcher:文本匹配器,作用按照正则表达式的规则去读取字符串,从头开始读取。在大串中去找符合匹配规则的子串。
时间相关类
Date时间类:
Date类是一个Javabean类,用来描述时间,精确到毫秒。
利用空参构造创建的对象,默认表示系统当前时间。
利用有参构造创建的对象,表示指定的时间
//创建日期对象 Date date = new Date(); Date date = new Date(指定毫秒值); //修改时间对象中的毫秒值 setTime(毫秒值); //获取时间对象中的毫秒值 getTime();
SimpleDateFormat类作用
格式化:把时间变成我们喜欢的格式
解析:把字符串表示的时间变成Date对象
常用模式:
Calendar
Calendar代表了系统当前时间的日历对象,可以单独修改、获取时间中的年,月,日
细节:Calendar是一个抽象类,不能直接创建对象。
JDK8新增时间类
新增时间类:
(1)Date类的Zoneld时区
(2)Date类Instant时间戳
(3)Date类ZoneDateTime带时区的时间
包装类
包装类:基本数据类型对应的引用类型。
后面是包装类。
Integer
创建对象: Integer i1 = Integer.valueOf(127); //等价于 Integer i1 = 127;
后面的等价于就是自动装箱的操作。
自动装箱:把基本数据类型会自动的变成其对应的包装类
自动拆箱:把包装类自动的变成其对象的基本数据类型
8种包装类中,除了Character都有对应的parseXxx的方法进行类型转换。
常用算法
查找
1、直接查找:效率低
2、二分查找,针对的是有序排列。有最大值,中间值,最小值。通过中间值与要查找数值进行比较,调整最大值或最小值所在的位置。
3、分块查找:(1)前一块中的最大数据,小于后一块中所有的数据(块内无序,快间有序)(2)块数数量一般等于数字的个数开根号(3)先确定要查找的元素在哪一块,然后在块内挨个查找。
排序
1、冒泡排序
2、选择排序
3、插入排序
4、快速排序
Arrays
方法名
排序规则:o1 - o2 是升序排列,o2 - o1 是降序排列。
Lambda
()->{ } ()对应着方法的形参, ->固定格式,{}对应着方法的方法体
注意:
(1)Lambda表达式可以用来简化匿名内部类的书写
(2)Lambda表达式只能简化函数式接口的匿名内部类的写法。
(3)函数式接口:有且仅有一个抽象方法的接口叫做函数式接口,接口上方可以架@Functionalinterface注解
好处:Lambda是一个匿名函数,可以把Lambda表达式理解为是一段可以传递的代码,它可以写出更简洁,更灵活的代码。
省略写法:
(1)参数类型可以不写
(2)如果只有一个参数,参数类型可以省略,同时()也可以省略。
(3)如果Lambda表达式的方法体只有一行,大括号,分号,return可以省略不写,需要同时省略。
集合进阶
单列集合(每次只能添加一个元素)
单列集合最顶级的是Collection
Collection下面又分为List 和 Set
List又分为ArrayList,LinkedList ,Vector
Set又分为HashSet和TreeSet,
其中HashSet又有LinkedHashSet
上述中,Collection,List,Set是接口
其他的类是实现类。
List系列集合:添加的元素是有序(存取顺序一样)、可重复、有索引。Set系列集合:添加的元素是无序、不重复、无索引。
Collection
无法直接创建对象:Collection<String> coll = new ArrayLiat<>();
Collection的遍历方式:
一、迭代器遍历
迭代器不依赖索引,在Java中的类是Iterator,是集合专用的遍历方式。
注意:
(1)当前没有元素还是强行获取,则会报错NoSuchElementException
(2)迭代器遍历完毕,指针不会复位
(3)循环中只能用一次next方法
(4)迭代器遍历时,不能用集合的方法进行增加或者删除
二、增强for遍历
增强for的底层就是迭代器,为了简化迭代器的代码书写的。只有单列集合和数组才能用增强for进行遍历。
格式: for (元素的数据类型 变量名:数组或者集合){ }
快速 生成:for之后点回车
注意:
(1)修改增强for中的变量,不会改变集合中原本的数据
三、Lambda表达式遍历
更简单,更直接的遍历集合的方式。
List
Collection的方法List都继承了。
在删除元素,调用remove方法的时候,如果方法出现了重载现象,优先调用,实参跟形参类型一致的那个方法。
List的遍历方式:
一、迭代器遍历
二、增强for
三、Lambda表达式
四、普通for循环
五、列表迭代器
相比之前的迭代器,增加了previous,可以往前进行查找元素。
ArrayList
ArrayList的底层是数据结构。
底层原理:
(1)利用空参创建的集合,在底层创建一个默认长度为0的数组
(2)添加第一个元素时,底层会创建一个新的长度为10的数组
(3)存满时,会扩容1.5倍
(4)如果一次添加多个数据,1.5倍放不下,则新创建数组的长度以实际为准
LinkedList集合
底层结构是数据结构中的双链表,查询慢,增删快。
具有直接操作首位元素的特有的API。
泛型
泛型可以在编译阶段约束操作的数据类型,并进行检查。
格式:<数据类型>
泛型只能支持引用数据类型。
好处:统一了数据类型;在运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为在编译阶段类型就能确定下来
细节:(1)泛型中不能写基本数据类型(2)指定泛型的具体类型后,传递数据时,可以传入该类类型或者其子类型(3)如果不写泛型,类型默认是Object。
泛型接口:(1)实现类给出具体的类型(2)实现类延续泛型,创建对象时再确定
泛型的继承和通配符
泛型不具备继承性,但是数据具备继承性。
泛型的通配符是:? 也表示不确定的类型,可以进行类型的限定
? extends E : 表示可以传递E或者E所有的子类类型
? super E:表示可以传递E或者E所有的父类类型
用<E> 的时候需要前后定义,而用例如<? extends E>的时候只需要定义后面即可。
应用场景:(1)如果我们定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类,泛型方法,泛型接口。
(2)如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以泛型的通配符了
红黑树
红黑树是一种特殊的二叉查找树,红黑树的每一个节点上都有存储位表示节点的颜色。每一个节点可以是红或者黑;红黑树不是高度平衡的,它的平衡是通过”红黑规则”进行实现的。
红黑规则:
(1)每一个节点或是红色,或者是黑色
(2)根节点必须是黑色
(3)如果一个节点没有子节点或者父节点,则该节点相应的指针属性值位Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的
(4)如果某一个节点是红色,那么它的子节点必须是黑色的(不能出现两个红色节点相连的情况)
(5)对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
红黑树添加规则:(1)默认颜色:添加节点默认是红色的(效率高)
set系列合集
无序:存取顺序不一致
不重复:可以去除重复
无索引:没有带索引的方法,所以不能使用普通for进行遍历,也不能通过索引来获取元素
实现类:
(1)HashSet:无序,不重复,无索引
(2)LinkedHashSet:有序,不重复,无索引
(3)TreeSet:可排序,不重复,无索引
HashSet
HashSet集合底层采取哈希表存储数据。哈希表是一种对于增删改查数据性能都较好的结构
哈希值:对象的整数表现形式。(1)根据hashCode方法算出来的int类型的整数(2)该方法定义在Object类中,所有对象都可以调用,默认使用地址值进行计算(3)一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值。
对象的哈希值特点:(1)如果没有重写hashCode方法,不同对象计算出的哈希值是不同的。(2)如果已经重写了hashCode方法,不同对象只要属性值相同,计算出的哈希值就是一样的。(3)在小部分情况下,不同属性值或者不同的地址值计算出来的哈希值可能一样(哈希碰撞)
哈希值插入:创建一个默认长度为16,默认加载因子为0.75(用于扩展数组)的数组,数组名为table
根据元素的哈希值跟数组的长度计算出存入的位置
int index = (数组长度 - 1) & 哈希值
如果当前位置为null,则直接存入
如果当前位置不为null,则调用equals方法比较属性值,新元素直接挂在老元素下面。
当挂载的链表大于8,而且数组的长度大于等于64的时候,当前的链表会转换成红黑树。
如果集合中存储的是自定义对象,必须要重写hashCode和equals方法
LinkedHashSet
(1)有序,不重复,无索引 (2)这里的有序指的是保证存储和取出的元素顺序一致
(3)原理:底层数据结构依然是哈希表,只是每个元素又额外多了一个双链表的机制记录存储的顺序。
TreeSet
特点(1)不重复,无索引,可排序(2)可排序:按照元素的默认规则(从小到大)排序。
(3)TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都比较好。
排序规则:(1)对于数值类型:Integer,Double,默认按照从小到大的顺序进行排序
(2)对于字符,字符串类型:按照字符在ASCLL码表中的数字升序进行排序。
TreeSet的两种比较方式:1、要实现Comparable接口,重写compareTo方法,指定比较规则
2、比较器排序:创建TreeSet对象的时候,传递比较器Comparator指定规则。
默认使用的是第一种,当第一种不能满足当前需求的时候,就使用第二种。
根据不同的情况,选择合适的单列集合: