JavaSE
2020-09-27 10:34:01 5 举报
AI智能生成
Java基础吐血整理
作者其他创作
大纲/内容
概述环境搭建
小知识点
应用方面
ctrl+c 强制停止正在运行的程序
Math.random随机小数
Random random = new Random;int a = random.nextInt(x);随机获得一个小于x的数
\"\".equals 用于引用数据类型
== . equals 与 !的应用解释
== 比较的是地址,不是内容。所以当比较字符串时,==不够准确。
比较字符串时,应使用 s1.equals(s2) ,可准确的比较字符串内容。
当比较两个字符串不相同时,可使用 !s1.equals(s2)。 !(逻辑运算符:非)代表“不是”
关于类和对象
A a = new A(); A a1 = a;a1等同于a的地址
可以在类里建其他类的对象class B{ A a = new A(); C c ;}public B(){ c = new C();}
循环结束
在循环前加个“常量名词”可以在想要结束循环时加 ”break + 常量名词“不用加“return”结束整个函数
Eclipse
工具的基本使用:
修改编辑字体:windows -> Preferences -> General -> Appearance -> Colors And Fonts -> Basic -> Text Font \t\t修改输出字体:windows -> Preferences -> General -> Appearance -> Colors And Fonts -> Debug ->\t\t重置窗口布局:windows -> Perspective -> Reset Perspective
Eclipse导入外部项目
File -> Import -> General -> Existing Projects into Workspace -> Browse -> 项目的根文件夹 -> Finish
格式化代码
Ctrl + Shift + F
构造方法快捷键
source
Generate Constructor using Fields
封装快捷键
Generate Getters and Setters
JavaSE
语言基础
变量
计算机内存中的一块存储空间,是存储数据的基本单位
组成部分
数据类型
变量名
值
声明方式
先声明,再赋值
数据类型 变量名;变量名 = 值;
声明并赋值
多个同类型变量的声明与赋值
基本数据类型
整数
byte
1字节
-2^7~2^7-1
short
2字节
-2^15~2^15-1
int
4字节
-2^31~2^31-1
long
8字节
-2^63~2^63-1
小数
float
double
布尔
boolean
字符
char
转义字符
子主题
\\'
\\\"
\\\\
\\t
\
引用数据类型
字符串
String
数组
对象
类型的转换
自动类型转换
两种类型互相兼容,目标类型大于源类型
强制类型转换
两种类型相互兼容,目标类型小于源类型
转换规则
整数长度足够,数据完整
整数长度不够,数据截断
小数强转整数,数据截断
字符整数互转,数据完整
保证正整数转换成字符,可以正常显示
boolean不可与其他类型转换
运算符
算数运算符
+ - * / % ++ --
赋值运算符
= += -= *= /= %=
关系运算符
> < >= <= == !=
逻辑运算符
&& || !
三元运算符
布尔表达式 ? 结果1:结果2
选择结构与分支结构
概念:根据已知条件进行落尽判断,满意条件后执行相应的操作
选择结构
基本if选择结构
if else选择结构
多重if选择结构
相互排斥,有一个为true,其他选择不在执行,适用于区间判断
嵌套if选择结构
可以在一个选择结构当中,语法正确、格式正确的情况下,可以任意组合
分支结构
switch
可判断的byte 、short 、int、char、String(JDK7+)
switch中的多个case取值不可相同
switch有自动向下贯穿的特性,如需要在某个选项执行后中止,需要追加break关键字
局部变量
概念:声明在函数内部的变量,必须先赋值在使用
作用范围:从定义行开始到所在的代码块结束
注意:多个变量在重合的作用范围内,不可出现重名
循环结构
概念:通过某个条件,重复的执行一段逻辑代码
while
int i= 0;while(i <= ?){ i++;}
首次既有入口条件,先判断,在执行,适用于循环次数明确的情况
do while
do{ }while(条件判断);
首次没有入口条件,先执行,在判断,适用于循环次数不明确的情况
for
for(int i = ? ;i <=?; i++){ }
流程控制语句
break
中止,跳出:switch分支结构,循环结构
continue
结束本次,进入下一次循环
嵌套循环的概念
在一个完整的循环结构中,嵌套另一个循环结构
外层控制循环次数,内层控制单次循环操作
函数
概念:实现特定功能的一段代码,可反复使用。
定义
定义: public static void 函数名称(){//函数的主体(功能代码)}
位置
定义在类的内部,与main函数并列。多数情况下,定义在main函数的下面
函数调用
函数名称();public static void 函数名称 ( 无参 ) { //局部变量的声明 }
函数名称(实参);public static void 函数名称 ( 形参 ) { //局部变量的声明 }
返回值
定义返回值类型
基本数据类型、引用数据类型、void
return value;
函数可以返回一个结果,类型必须与函数定义的返回值类型一致。
一个函数只能有一个返回值,如果函数中包含分支,需要保证所有的分支都有正确的返回值。
return的两种用法:
return value; //表示结束当前函数,并伴有返回值,返回到函数调用处。(有具体的返回值类型)
return; //表示结束当前函数,直接会返回到函数调用处。(返回值类型是void)
递归
实际再发中,递归可以解决一些具有既定规律的问题。
当需要解决的问题可以拆分成若干个小问题,大问题、小问题的解决方法相同,有特定的规律,函数自己调用自己。
设置有效的出口条件,避免无穷递归。
总结
注意
一个类中可以定义多个函数,函数之间属于并列关系,不可嵌套。
经验
一个函数只做一件事。
好处
子主题减少代码冗余。提高复用性。提高可读性。提高可维护性。方便分工合作。
概念
一组连续的存储空间,存储多个相同数据类型的值。
数组的创建:
数据类型[] 数组名 = new 数据类型[长度];\t// int [] a = new int[5];
数组的组成概述:
数组中的每个“格子”称为“数组的元素”。
对元素的访问分为:“赋值”、“取值”。
访问元素时,需要通过“下标”(从0开始,依次+1,自动生成)
访问的语法:数组名[下标]; //存:a[0] = 10; 取:a[0]
下标的范围:0 ~ 数组的长度-1 ,如果不在有效下标内,产生java.util.ArrayIndexOutOfBoundsException:错误下标
数组的遍历
从头至尾,逐一对数组的每个元素进行访问
数组名.length
可动态获取数组长度
在没有为数组元素赋值的情况下,依旧可以正确访问
0
0.0
\\u0000
false
其他
null
数组的”扩容“
创建数组时,必须显示指定长度,并在创建之后不可更改长度。
思路
创建长度大于原数组的新数组。
将原数组中的数据依次复制到新数组当中。
复制
循环将原数组中的所有元素数据逐一赋值给新数组。
地址的替换
图片解析
基本数据类型的变量存储的是值 也就是栈
引用数据类型的变量存储的是地址 地址也就是堆
nums = newNums; //将新数组的地址,赋值给nums变量,进而在后续操作nums时,则操作长度更大的新数组。
可变长参数
可接收多个同类型实参,个数不限,使用方式与数组相同。
语法
数据类型... 形参名 //必须定义在形参列表的最后,且只能有一个,支持0~N个参数。
int... = int[] String... = String[] char... = char[] double... = double[]
排序
冒泡排序:
1).\t相邻的两个值比较大小,互换位置。
2).\t记忆:外层 length - 1 ;内层 length -1 - i
选择排序
固定值与其他值比较大小,互换位置。
记忆:外层 length - 1 ;同时外层i作为固定值,内层的j = i+1作为其他值的起始
java.util.Array.sort(数组名) 只能用于升序
补充:嵌套循环约定俗称的变量命名,一重循环 i;二重循环j;三重循环k;
二维数组
一维数组中的一维数组,数组中的元素,还是数组。
先声明再分配空间
数组类型[][] 数组名数组名 = new 数据类型[高维长度][低维长度]
声明并分配空间
数组类型[][] 数组名= new 数据类型[高维长度][低维长度]
声明并赋值(繁)
数组类型[][] 数组名 = new 数据类型[高维长度][] // 不规则数组自行new低数组 数组名[高维数组] = new[低维数组]
声明并赋值(简)
高维数组中的每一个元素,保存了低维数组的地址。访问array[0]等价于在访问0x0000A111(\"二维数组的内存分配图\")
面向对象
程序的概念:
程序是为了模拟现实世界、解决现实问题而使用计算机语言编写的指令集合。
什么是对象?
一切客观存在的事物都是对象,万物皆对象。
初期:看得见、摸得着、并真实存在,都是对象。
对象有什么?
子主题任何对象,一定有自己的特征和行为。
特征和行为:
特征:称为属性,一般为名词,代表对象都有什么。
行为:称为方法,一般为动词,代表对象能做什么。
程序中的对象
程序如何模拟现实世界?
(1).\t现实世界中,都是对象,程序中也应有对象。(2).\t程序当中必须具有和现实中相同的对象,用以模拟。(3).\t使用程序中的对象,代表现实中的对象,并执行操作,解决现实问题。
解析
现实与程序:
(1).\t现实中的对象,来自于模板,通过模板造出来的实体,即是现实的对象。(2).\t程序中的对象,来自于模板(“类”),通过类造出来的实体,及时程序中的对象。
类与对象的关系:
类:定义了对象应具有的特征和行为,类是对象的模板。
对象:拥有多个特征和行为的实体,对象是类的实例。
类的抽取
在一组相同或类似的对象中,抽取出共性的特征和行为,保留所关注的部分
实例变量与局部变量的区别
局部变量定义在方法或方法的结构当中,无默认值,使用范围是从定义行到包含其结构结束,不允许重名
实例变量定义在类的内部,方法的外部,默认值为字面值(与数组相同),仅在本类中有效,可与局部变量重名,局部变量优先
方法重载(Overload)
在一个类中定义多个相同名称的方法。
要求
方法名称相同
参数列表不同
与访问修饰符、返回值无关
屏蔽用户的使用差异,方便。
构造方法(Constractor)
概念:类中的特殊方法,主要用于创建对象。
特点
名称与类名完全相同(包括大小写)。
没有返回值类型。
创建对象时(new对象时),触发构造方法的调用,不可通过句点的形式手工调用。
注意:如果没有在类中显示定义过构造方法,则编译器默认提供无参构造方法。如果已经手动添加过有参构造方法,则无参构造方法不再默认提供,必须手动添加无参构造方法)
this关键字
this代表“当前实例”,即是模板中的当前对象,模板服务与哪个对象,this就指向哪个对象。
this第一种用法:调用本类中的实例属性、实例方法。例如:this.name、this.run()。
this第二种用法:调用本类中的其他构造方法。例如:this()、this(实参)。注意:必须在构造方法的首行。
默认来讲,实例属性和方法前的this.隐式存在
三大特性
封装
概念:尽可能隐藏对象的内部实现细节,控制对象的修改及访问的权限。
private的访问修饰符,修饰属性,达到本类可见的效果。
get/set方法是外界访问私有属性的唯一通道,方法内部可对数据进行过滤。(可在set方法中添加过滤条件)
提供公共访问方法,以保证数据可以正常录入。
private构造方法达到私有类的效果,别人无法看见
银行案例总结
继承
程序中的继承,是类与类之间特征和行为的一种赠与或获得
类与类之间必须满足“is a”的关系
父类的选择:功能越精细,重合点越多的,越接近直接父类
父类的抽象:根据程序需要使用到的多个具体类,进行共性的提取,进而定义父类
在一组相同或类似的类中,抽取出共性的特征和行为,定义在父类中,实现重用
产生继承关系之后,子类可以使用父类中的属性和方法,也可定义子类独有的属性和方法
完整的子类 = 父类共性 + 子类独有
好处:既提高代码的复用性,又提高代码的可扩展性
Java为单继承,一个类只能有一个直接父类,但可以多级继承,属性和方法逐级叠加
不可继承:
父类的构造方法,子类不可继承。
父类中由private修饰的成员,不可继承(不可见)。
父类中由default修饰的成员,子类不在同包时,不可继承(不可见)。
访问修饰符
方法的覆盖/重写(Override)
当父类提供的方法无法满足子类需求时,可以在子类中定义和父类相同的方法进行覆盖。
方法名、参数表、返回值,必须与父类完全相同。
访问修饰符应与父类相同或比父类更宽泛。
执行机制:子类覆盖父类方法后,优先执行子类覆盖后的方法版本。
super关键字
第一种用法:在子类中,可以通过\" super. \"的形式访问父类的属性和方法,可解决一定的属性遮蔽、方法覆盖后的父类成员调用问题。
第二种用法:super() 表示在子类构造方法的首行,调用父类的无参构造方法。
继承关系下的对象创建:
继承关系下,构建子类对象时,会先构建父类对象。
由“父类共性”+ “子类独有”组合成一个完整的子类对象。
继承关系下的对象创建流程:
构建父类对象
初始化自身属性
执行自身构造方法中的逻辑代码
如果子类构造方法中,没有显示定义super()或super(实参),则默认提供super()。
同一个子类构造方法中,super()、this()不可同时存在。
多态
概念:父类引用指向子类对象,从而产生多种形态。
构成多态的前提,二者之间必须具有直接或间接的继承关系,父类引用可指向子类对象,进而形成多态。
父类引用仅可调用父类中所声明的属性和方法,不可调用子类独有的属性和方法。
多态两种应用场景:
场景一:使用父类作为方法形参,实现多态 调用方法时,可传递的实参类型包括:本类型对象+其所有的子类对象。
场景二:使用父类作为方法返回值,实现多态。 调用方法后,可得到的结果类型包括:本类型对象+其所有的子类对象。
多态的作用:
屏蔽子类间的差异。
灵活、耦合度低。
时间与空间的平衡、效率与安全的平衡
三大修饰符
abstract
父类:不够完整、不够具体、不该独立存在,如何解决?通过abstract修饰类,意为抽象类,不能new对象
abstract的意思:抽象的,似是而非的,像,却又不是,具备某种对象的特征,但不完整。
abstract修饰类,意为“不够完整、不够具体,不该独立存在”
即为抽象类,不能独立new对象。
可被子类继承,对子类提供共性的属性和方法。
可声明引用,更纯粹的使用多态。
抽象类的构造方法的作用:构建子类对象时,先构建父类对象,由父类共性+子类独有组成完整的子类对象。
abstract修饰类:不能new对象,但可以声明引用。
abstract修饰方法:只有方法声明,没有方法实现。(需包含在抽象类中)
抽象类中不一定由抽象方法,但由抽象方法的类一定是抽象类。
子类继承抽象类之后,必须覆盖父类当中所有的抽象方法,否则子类还是抽象类。
static
静态与实例的区别:
实例属性是每个对象各自持有的独立空间(多份),对象单方面修改,不会影响其他对象。
方法区
静态属性是整个类共同持有的共享空间(一份),任何对象修改,都会影响其他对象。
静态的概念:
static可以修饰属性和方法,即为静态属性(类属性)、静态方法(类方法)
静态成员是全类所有对象共享的,全类只有一份,不因创建多个对象而产生多份。
不必创建对象,也可通过类名,直接访问静态成员。
经验:访问静态属性和方法时,可直接通过“类名.静态属性名”以及“类名.静态方法名”(推荐)
静态的特点:
静态方法允许直接访问静态成员。
静态方法不能直接访问非静态成员。
静态方法中不允许使用this或super关键字。
静态方法可以继承,不能覆盖,没有多态。
类加载:
JVM首次使用某个类时,将该类的.class文件加载到内存中,进行保存。
II.加载时机:
创建对象
创建子类对象
调用静态属性和方法
Class.forName(“全限定名”); //主动的加载一个类
静态代码块:
类加载时,触发静态代码块的执行(仅一次)。
执行地位:静态属性初始化之后。
作用:可为静态属性赋值,或必要的初始行为。
\t总结:
static修饰的成员为静态成员,无需创建对象,可直接通过类名访问。
静态方法中不能使用this或super。
静态方法可以继承、不能重写、没有多态。
静态代码块在类加载时被执行,且只执行一次。
动态代码块和静态代码块执行初始工作的思路
动态代码块
静态代码块
final
修饰类:此类不能被继承
修饰方法:此方法不能被覆盖
\t修饰变量:此变量值不可改变--常量(无初始值、只允许赋值一次)
1).\t局部常量:显示初始化
2).\t实例常量的赋值:显示初始化、动态代码块、构造方法。
a).实例常量赋值deadline:在构造方法完成之前,为实例常量赋值即可。
b).如果在构造方法中为实例常量赋值,必须保证所有的构造方法都可正确赋值。
3).\t静态常量的赋值:显示初始化、静态代码块。
a).\t静态常量赋值deadline:在类加载完成之前(通过类名调用之前),为静态常量赋值即可。
不同常量类型的特点:
1).\t基本数据类型常量:值不可变。
2).\t引用数据类型常量:地址不可变。
接口
\t接口的概念:
接口是种能力和约定
接口的定义:能力
方法的定义:约定
经验:Java为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力。
经验:接口支持多实现,可为类扩充多种能力。
接口的语法:
相当于特殊的抽象类,定义方式、组成部分,与抽象类类似。
接口中只能定义公开静态常量(变量)
接口中只能定义公开抽象方法(方法)
接口不是类
接口与抽象类的异同:
相同:
1).\t可以编译成字节码文件
2).\t不能创建对象。(接口不是类,不是模板的概念,也没有构造方法)
3).\t可以声明引用。
4).\t具备Object定义的方法。
不同:
1).\t接口中的属性只能是公开静态常量(隐式使用public static final修饰)
2).\t接口中的方法只能是公开抽象方法(隐式使用public abstract修饰)
3).\t没有构造方法、没有动态代码块、没有静态代码块
接口的规范:
任何类在实现接口时,必须实现接口中所有的抽象方法,否则此类为抽象类。
实现接口中的抽象方法时,访问修饰符必须是public。
接口引用:
同父类一样,接口也可声明为引用,并指向实现类对象。
注意:
1).\t仅可调用接口中所声明的方法,而不可调用实现类中独有的方法。
2).\t可强转回实现类的本身类型,进行独有的属性和方法的调用。(强转前通过instanceof判断)
接口的多态:
不再关注具体的类型,而是关注行为
常见关系
类与类:单继承,extends父类名称
接口:
接口是一种标准。
耦合度:模块与模块之间的关联程度,关联的越密切,耦合越高,关联的越松散,耦合越低。
常量接口:
将多个常用于表示状态和固定值的变量,以形态常量的形式定义在接口中统一管理,提高代码的可读性。
接口回调思路
接口的好处
程序的耦合度降低
更自然的使用多态
设计与实现完全分离
更容易搭建程序框架
更容易更换具体实现
常用类
内部类
成员:
1).\t在类的内部定义,与实例变量、实例方法同级别的类。
2).\t属于外部类的一个实例部分,创建内部类对象,必须依赖外部类对象。
3).\tOuter out = new Outer();Outer.Inner in = out.new Inner();
4).\t当外部类、内部类存在重名属性时,有限访问内部类属性,通过外部类类名.this.外部类实例属性
5).\t成员内部类不能定义静态成员。
静态:
1).\t不依赖外部类对象,可直接创建或通过类名访问,也可声明静态成员。
2).\tOuter.Inner.静态成员Outer.Inner in = new Outer.Inner();
局部:
1).\t定义在外部类的方法中,作用范围和创建对象的范围仅限当前方法中。
2).\t局部内部类访问外部类局部变量时,因无法保障变量的生命周期与自身相同,所以修饰为final。
jvm垃圾清理周期图
3).\t隐藏类的信息、限制类的使用范围。
匿名:
没有类名的局部内部类,正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写
2).\t必须继承一个父类或实现一个接口。
3).\t定义类、实现类、创建对象的语法合并,只能创建一个该类的对象。
定义格式:new 父类类名(){ 方法区};
4).\t优:减少代码量,书写的思路流畅。
5).\t劣:可读性较差。
以后可能作为接口回调的方法
Object
超类、基类,所有类的直接或间接父类,位于继承树的最顶端
任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承
Object类中所定义的方法,是所有对象都具备的方法
Object类型所定义的方法,是所有对象都具备的方法
任何参数,可接受任何对象
作为返回值,可返回任何对象
getClass()方法
public final Class<?> getClass(){}
返回引用中存储的实际对象类型
应用: 通常用于判断两个引用中实际存储对象类型是否一致
hashCode()方法
public int hashCode(){}
返回该对象的十进制的哈希码值
哈希算法根据对象的地址或字符串或数字计算出来的int类型的数值。
哈希码并不唯一,可保证相同对象返回相同哈希码,尽量保证不同对象返回不同哈希码
toString()方法
public String toString(){}
返回该对象的字符串表示(表现形式)
可以根据程序需求覆盖该方法,如:展示对象各个属性值
Object stu = new Student();System.out.println(stu.toString());==
Sysotem.out.println(stu.getClass() + \"@\" + Integer.toHexstring(stu.hashCode()));
equals()方法
public boolean equals(Object obf){}
可进行覆盖,比较两个对象的内容是否相同
方法equals()方法覆盖步骤
比较两个引用是否指向同一个对象
判断obj是否为null
判断两个引用指向的实际对象类型是否一致
依次比较各个属性值是否相同
finalize()方法
当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列
垃圾对象:没有有效引用指向此对象,为垃圾对象(两个对象相互引用也为无效引用)
垃圾回收:由GC销毁垃圾对象,释放数据存储空间
自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象
手动回收机制:使用System.gc();通知JVM执行垃圾回收(执行有间隔时间)如果在执行过程中,被别的有效引用指向此对象,那么垃圾回收将不再回收此对象,容易造成内存泄漏
不建议使用子类覆盖Object中的finalize()方法去手动执行垃圾回收
包装类
概念:
基本数据类型所对应的引用数据类型
Object可统一所有数据,包装类的默认值是null
包装类中实际上就是持有了一个基本类型的属性,作为数据的存储空间(Byte中有一个byte属性),还提供了常用的转型方法,以及常量,既可以存储值,又具备了一系列的转型方法和常用常量,比直接使用基本类型的功能更强大
类型转换与装箱、拆箱
8种包装类提供不同类型间的转换方式
Number父类中提供的6个共性方法
byte b1 = b.byteValue();
short s1 = 对象名.shortValue();
int i1 = 对象名.intValue();
long l1 = 对象名.longValue();
double d1 = 对象名.doubleValue
float f1 = 对象名.floatValue;
parseXXX()静态方法(将字符串转化成基本数据类型)
byte b1 = Byte.parseByte(\"123\");
byte b2 = new Byte(\"123\").byteValue(); 先通过构造方法将字符串转化为对象,然后通过byteValue转化为基本数据类型
valueOf()静态方法(将字符串转化为包装类)
Byte b3 = Byte.valueOf((byte)123);整数默认为int 所以要强转为byte
Byte b4 = new Byte(\"123\");通过构造方法在创建对象时转化为Byte类型
注意:需保证类型兼容,否则抛出NumberFormatException异常
JDK5.0之后,自动装箱、拆箱。基本数据类型和包装类自动转换
整数缓存区
java预先创建了256个常用的整数包装类型对象(-128-127)赋值在此范围内的都会指向同一个地址
存入数组的过程
Short s=new Short(\"129\");\t\tbyte a=s.byteValue();\t\tSystem.out.println(a);
结果为-127(因为byte的范围为-128到127所以就变成了-128+1)
在实际应用对象中,对以创建的对象进行复用
字符串是常量,创建之后不可改变
字符串字面值存储在字符池中,可以共享
String s = “Hello”;产生一个对象,字符串池中存储
String s = new String(\"Hello\");产生两个对象,堆,池各存储一个
方法
String s = \"Hello\";
public char charAt(int index):根据下标获取字符s.charAt(1);结果为“e”
public boolean contains(Strng str);判断当前字符串中是否包含strs.comtains(\"Hel\");结果为true s.comtains(\"Ho\");结果为flase
public char[] tocharArray();将字符串转化为字符数组并返回char[] chs = s.tocharArray();
public int lostIndexOf(String str)查找字符串最后一次出现的下标索引(比较👆indexOf())
public int length()返回字符串的长度
public String trim()去掉字符串前后的空格
public String toUpper(asel);将小写转化为大写
public String toLower(asel);将大写转化为小写
对象名.equalsIgnorelase(另一对象)不论大小写,两者进行比较
public boolean endWith(String str)判断字符串是否以str结尾
public boolean startWith(String str)判断字符串是否以str为前缀
public String[] split(String str)根据str将字符拆分成数组,元素多少根据拆分的数量,拆分后str将消失
public String subString(int beginIndex)根据输入的值作为截取返回新字符串(从输入的值开始)
public boolean isEmpty()字符串数组长度为零时返回true,表示为空串
getBytes()
byte[] getBytes() String编码成一个序列使用平台的默认字符集字节,结果存放到一个新的字节数组。
byte[] getBytes(Charset charset)String编码为一个字节序列使用给定的 charset,结果存放到一个新的字节数组。
byte[] getBytes(String charsetName)String编码成一个序列使用指定的字符的字节,并将结果存储到一个新的字节数组。
StringBuffer
可变长字符串,JDK1.0提供,运行效率慢、线路安全
StringBuilder
可变长字符串,JDK5.0提供,运行效率快、线路不安全
保存在池中的条件:1.直接声明,2.首次出现
String s1= \"abc\"; //(保存在池中)String s2 = s1 + \"def\"; //会自动运行StringBuilder会在堆中建一个新的stringBuilder对象,进行拼接,最后通过toString()方法返回一个new String () 对象给s2(保存在堆中)s2.inter(); //过s2.inter();在池中创建一个为“abcdef”的字符串(池中没有创建过“abcdef”)String s3 = \"abcdef\"; //复用s2保存在池中的地址s2 == s3 true
inter()方法的使用----------------------------------------------------------------------------
String s1= \"abc\"; //(保存在池中)String s2 = s1 + \"def\"; //会自动运行StringBuilder会在堆中建一个新的stringBuilder对象,进行拼接,最后通过toString()方法返回一个new String () 对象给s2(保存在堆中)String s3 = \"abcdef\"; //在池中创建一个新的“abcdef”;/*s2.inter(); //池中已经有一个“abcdef”的地址,所以不能创建,但是会返回一个名为“abcdef”的地址,需要赋值给新的变量。s2 == s3 flase*/String s4 = s2.inter();s3 == s4; true
BigDecimal
位置:java.math包中
作用:精确计算浮点数
创建方式:BigDecimal bd = new BigDecimal(“1.0”);
加:BigDecimal add(BigDecimal bd )
减:BigDecimal subtract(BigDecimal bd )
乘:BigDecimal multiply(BigDecimal bd )
除;BigDecimal divide(BigDecimal bd )
除;BigDecimal divide(BigDecimal bd ,int scal, RoundingMode mode)
参数scal:指定精确到小数点后几位
参数mode:
指定小数部分得取舍模式,通常采用四舍五入得模式
取值为BigDecimal.ROUND_UP
集合
什么是集合
概念:对象的容器,存储对象的对象,可代替数组
特点:容器的工具类,定义了对多个对象进行操作的常用方法
位置:java.util.*;
Collection体系集合
特点:代表一组任意类型的对象,无序、无下标
Collections工具类:
概念:集合工具类,定义了除了存取以外的集合常用方法。
I.\tpublic static <T extends Comparable<? super T>> void sort(List<T> list) //排序,要求:必须实现Comparable,必须可与自身类型比,以及父类型比
II.\tpublic static void reverse(List<?> list) //反转、倒置元素
III.\tpublic static void shuffle(List<?> list) //随机重置顺序
Collection子接口
List
特点:有序、有下标、元素可以重复
List实现类
使用接口引用执向实现类对象的定义方法List list = new 实现类();作用:更容易更换具体实现
ArrayList
数据结构实现,查询快、增删慢
JDK1.2版本,运行效率快、线程不安全。
ArrayList只能存储对象类型
通过Array.asList();方法可以快速创建一个长度固定的集合,但不可改变
对象构造方法
new ArrayList(); JDK7及之前,无参构造方法直接创建长度为10的Object数组,用还是不用,数组就在那里,(占内存) JDK8之后,无参构造方法直接创建长度为0的数组,如果不用,不占空间,只有当真正插入元素时,再分配数组空间(10个空间)
new ArrayList(Collection<? extends E> c);构造一个包含指定集合的元素的列表,它们在集合的迭代器返回的顺序中返回。
new ArrayList(int initialCapacity);用指定的初始容量构造一个空列表。
I.\tJDK8的ArrayList,实际初始长度是0II.\t首次添加元素时,需要实际分配数组空间,执行数组扩容操作III.\t真正向数组中插入数据,(Lazy懒)用的时候再创建,或再加载,有效的降低无用内存的占用
Vector
I.\t数组结构存储,查询快,增删慢。
II.\tJDK 1.0发布,执行效率慢,线程安全。
LinkedList
I.\t链表(链接列表)结构存储,查询慢、增删快。
II.\t了解:Queue接口:队列、双端队列
III.\t了解:栈结构Last In First Out(后进先出)
IV.\t了解:队列结构First In First Out(先进先出)
LinkedList.first = Node对象(自身的值、null、下一个节点) LinkedList.last = Node对象(自身的值、上一个节点、null)
Set
无序、无下标,元素不可重复
方法:全部继承自Collection中的方法
Set实现类
HashSet
通过对元素的hashCode进行判断,若哈希码相同,再去判断是否为同一对象(地址),如果判断的对象地址不同,内容相同,则需要覆盖equals()方法去判断,内容相同返回true;
先判断hashCode是否一致,==比较地址,equals比较内容
(1)覆盖hashCode()方法大范围的保证相同的内容输出相同的哈希码,进行比较 public int hashCode() {//6个对象比较15次,原因是6个对象哈希码都相同\t\t//return 123;//固定值,所有对象都要比较\t\t//return this.age;//相对优化:所有对象返回相同哈希码,达到了可以去掉重复的目的,但是,效率又很低(该比的比,不该比的不比)\t\treturn this.name.hashCode() + this.age.hashCode() + this.sex.hashCode() + this.score.hashCode();\t}
(2)覆盖equals()方法进行判断,如果相同对象输出ture,不同对象,内容相同输入true拒绝插入public boolean equals(Object obj) {\t\tif(this == obj) return true;\t\tif(obj == null) return false;\t\tif(this.getClass() != obj.getClass()) return false;\t\tStudent s =(Student)obj;\t\tif(this.name.equals(s.name) && this.age.equals(s.age) &&\t\tthis.sex.equals(s.sex) && this.score.equals(s.score)) return true;\t\treturn false;\t}
HashSet的底层使用的HashMap类,即是将所有需要存入HashSet的值,直接保存在HashMap中
HashSet如何去掉重复?
LinkedHashSet
1).\t底层使用LinkedHashMap(链表结构)存储,节点形式单独存储数据,并可以指向下一个节点,通过顺序访问节点,可保留元素插入顺序
其他与HashSet工具相同,只是保留元素的插入顺序
Set子接口
SortedSet接口
TreeSet
实现了SortedSet接口,要求必须可以对元素排序。
所有插入元素,必须实现Comparable接口,覆盖compareTo方法。
根据compareTo方法返回0作为去重的依据,(意味重复)
在实现类中重新定义comparable()方法比较内容选择升序降序,当返回值为零时表示相同对象,不存入
public int compareTo(Student o) { System.out.println(\"compareTo被TreeSet的add方法回调\"); //升序//主要排序列 if(this.score < o.score) {//this小,this就靠前 return -1; }else if(this.score > o.score) {//this大,this就靠后 return 1; }else {//次要排序列//成绩相同,比另一个属性 if(this.age < o.age) { return -1; }else if(this.age > o.age) { return 1; }else{//次次要排序列//成绩和年龄相同,比姓名首字母 if(this.name.compareTo(o.name) < 0){ return -1; } else if(this.name.compareTo(o.name) > 0){ return 1; } else{//最后排序列//成绩和年龄和姓名相同,比性别 return this.sex.compareTo(o.sex); } }}
foreach循环:for(数据类型 变量名 : 容器名称){ //可遍历集合或数组(常用在无序集合上)}
Iterator(用与Collection)
1.获得一个迭代器 Itreator<数据类型> ir = 集合名.iterator();
2.判断,进行下一项:hasNext();是否有下一个元素可以遍历,有:true 没有:flash next();返回下一个元素
3.循环遍历 while(ir.hasNext()){ System.out.println(ir.next());}
泛型集合
基础
概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。
特点:
编译时即可检查,而非运行时抛出异常。
访问时,不必类型转换(拆箱)。
不同泛型之间引用不能相互赋值,泛型不存在多态。
高级
高级类别的知识,熟练应用,需要时间、经验的积累(常用名称:E = Element / T = Type / K = Key / V = Value)
概念:约束-规范类型
泛型的场景:
A).\t实例泛型:
类:创建对象时,为类所定义的泛型,进行参数化赋值
MyClass<Integer> mc1 = new MyClass<Integer>();\t\tMyClass<Double> mc2 = new MyClass<Double>();\t\tMyClass<String> mc3 = new MyClass<String>();class MyClass<E>{ //E代表一种通配,可以是任意类型,未指明类型前,为Object public void m1(E e) {//泛型可以动态 } public void m2(Object o) {//固定写死,不能变 }}
---------------------------------------------------------------------------------------------------------
接口:实现接口时,为接口所定义的泛型,进行参数化赋值
interface Comparable<E>{//可比较,可排序\tpublic int compareTo(E obj);//Object参数的通用,还是在具体业务场景中稍显麻烦}class MyStudent implements Comparable<MyStudent>{\tint age; public int compareTo(MyStudent obj) { if(this.age > obj.age) { return -1; } return 0; }}
B).\t静态泛型:
静态集合(形参条件)
//?代表任意泛型\t//可接受的是所有的动物集合\t/**\t * ? extends Animal 泛型类型必须是Animal的子类\t * ? extends Comparable 泛型类型必须是Comparable的实现类\t * ? super Dog 泛型类型必须是Dog或Dog父类\t */\tpublic static void m1(List<? super Dog> list) { \t}
静态集合(声明条件)形参中为T时,可以把返回值定义为T,用传进来的类型,返回一个同类型的对象或类型
//<T extends Comparable> 只要List集合中的元素,实现了Comparable接口就行//<T extends Comparable<Integer>> List集合中的元素,实现的Comparable接口,必须是Integer泛型的//目标:集合中的所有对象,必须具备本类型的两个元素进行比较的方法\tpublic static <T extends Comparable<T>> void m(List<T> list) {\t//当LIst<T>被传入实参后,要求T所代表的类型,必须实现Comparable接口,同时,接口泛型必须是T类型\t}
静态(声明条件)形参中为T时,可以把返回值定义为T,用传进来的类型,返回一个同类型的对象或类型
传入的实参必须是继承了number然后是Serializable 和 Comparable的实现类(才可以通过实参传入)public static <T extends Number & Serializable & Comparable> void m1(T t) {//宽泛(特别宽泛,不存在约束)\t}
List集合的元素实现(升级版)形参中为T时,可以把返回值定义为T,用传进来的类型,返回一个同类型的对象或类型
/**\t * 原案例:当LIst<T>被传入实参后,要求T所代表的类型,必须实现Comparable接口,同时,接口泛型必须是T类型(合理,但是过于严格)\t * 1.如果要求Comparable<T>必须是自身类型,则导致,无法对一组父类引用的对象进行排序\t * 2.故而加入<? super T> 实现Comparable接口时,无论是父类还是子类,都可以成为泛型参数\t * 参数化类型,类型安全\t */\tpublic static <T extends Comparable<? super T>> void m(List<T> list) { //Arrays.sort( new Student[5] ); for(int i = 0 ; i < list.size() - 1 ; i++) { Comparable c = (Comparable)list.get(i);// ClassCastException connot be convert Student to Comparable int result = c.compareTo(list.get(i+1)); // 1 -1 0 }\t}
Map体系集合
父接口的特点:存储一堆数据(Key - Value),无序、无下标,键不可重复,值可重复
实现类
HashMap
java1.2版本提供,线程不安全,运行效率快
允许null作为key或Value
HashMap底层是链表数组
HashMap算法:拿到任何一个对象好,通过hash(key)做运算,key>>>16(除以16),只可能得到0~15之间的一个数组,作为插入数组的下标
HashMap存入过程
HashSet存入过程
Hashtable
JDK1.0版本提供,线程安全,运行效率慢
不允许用null作为Key或Value
Properties
Key和Value都是String类型
setProperty();
getProperty();
主要用于存储key和value都是字符串的情况,常在读取配置文件之后,保存文件中的键值对。反射、JDBC
父类的put()方法里面的类型是Object,而Properties的put()中的类型是String所以基本数用于配置文件的读取
//将集合加载到文件中去userPros.store(new FileWriter(\"Files\\\\userPros.properties\
//把properties文件里的内容通过字符流加载到properties集合里userPros.load(new FileReader(file));
SortedMap
TreeMap
自动对key做排序
必须实现Comparable,根据compareTo的返回值去重
注意:HashMap和TreeMap 中的 Key 被HashSet和TreeSet重用 所以HashSet和TreeSet中的对象和值不可重复不可以重复
工具方法
V get(Object key)返回一个key键指定的值
Set<k> keySet() 返回整个key键
Collection<V> values()返回整个Key键的值
boolean containsKey(Object key)如果其中有值的话返回true
V remove(Object key)删除其中键的值,返回
boolean containsKey(Object key) 返回 true表示Map中有Key键中的值
boolean containsValue(Object value) 返回 true则表示这个值有一个或多个键。
三种遍历方法Map<String> mp = new HashMap<String>();
遍历方式一:KeySet();键-无序、无下标、不可重复Set<String> keys = mp.keySet();\t\tfor(String k : keys) { System.out.println(k); System.out.println(maps.get(k));\t\t}
遍历方式二: values(); 值 可以重复\t\tCollection<String> cs = mp.values();\t\tfor(String value : cs) { System.out.println(value);\t\t}
遍历方式3 entrySet(); 键值对 getKey(); getValue();(font color=\"#c41230\
集合总结
异常
概念:程序在运行过程中出现的特殊情况
异常处理的必须性:任何程序都可能存在大量的未知问题、错误;如果不对这些问题进行正确处理,则可能导致程序的中断,造成不必要的损失
Throwable:可抛出的,一切错误或异常的父类位于java.lang包中
Error:JVM、硬件、执行逻辑错误,不能手动处理
Exception:程序在运行和配置中产生的问题,可处理
CheckedException:受查异常,必须处理
RuntimeException:运行时异常,可处理,可不处理(仅有此一个类)
异常的产生
自动抛出异常:当程序在运行时遇到不合规范的代码结果时,会产生异常
手动抛出异常:语法:throw new 异常类型(\"实际参数\");
产生结果异常:相当于遇到return语句,导致程序因异常而终止
异常的传递
异常的传递:按照方法的调用链反向传递,如始终没有处理异常,最终会由JVM进行默认异常处理(打印堆栈跟踪信息)
受查异常:throws声明异常,修饰在方法参数列表后端
运行时异常:因可处理可不处理,无需声明异常
异常的处理
throws 异常类型
throws Exception 位于参数后,表示提供异常,一旦提供,不在此处解决异常,向上报告,在调用除解决异常或JVM打印堆栈跟踪信息
try{} catch(){}
try{ 可能出现异常的代码}catch(Exception e){ 异常处理的相关代码 e.printStackTrace()打印到标准错误流这个异常和回溯。 (打印堆栈跟踪信息) System.out.println(e.getMessage())输出错误的原因(构造方法提供private Message的赋值,没有setMessage()方法)}finally{ 无论是否出现异常,都需执行的代码结构,常用于释放资源}
常见异常处理结构
try{} catch{}
try{} catch{} catch{} (父类要在子类的下面,子类顺序无所谓,Exception的同级别的throwable的子类(满足需求才能太添加的)位置在父类前面即可)
try{} catch{} finally{}
try{} catch{} catch{} finally{}
try{} finally{}
多重catch,遵循从子(小)到父(大)的顺序,父类异常在最后。
finally的用法
//核心方法(每个用户都需要使用)5万try{ //使用资源对象-->发生了异常 //发生了异常}catch(Exception e){ e.printStackTrace();}finally{ //使用完毕,关闭资源}
自定义异常
场景:根据自身的需求去创建异常
class AgeInputException extends RuntimeException{\tpublic AgeInputException() {}//支持创建无异常原因信息的异常对象\tpublic AgeInputException(String message) {//提供有参构造方法,支持编写异常原因信息\t\tsuper(message);//调用父类的有参构造方法,为message属性赋值。\t}}
方法覆盖
带有异常声明的方法覆盖
方法名、参数列表、返回值必须和父类相同
子类的访问修饰符符合父类相同或是比父类更宽
子类中的方法,不能抛出比父类更宽泛的异常
//带有异常的方法覆盖(补充)//1.父类中方法声明了异常。子类重写后可声明也可不声明//2.父类中方法没有声明异常,则子类也不可以声明异常。//3.父类中方法声明了异常,子类可以声明的异常与其相等或是其子类//4.子类可以声明比父类更多的异常。必须小于其父类声明的异常
字节码文件运行过程
宏观
微观
多线程
初级多线程
进程:运行时的程序,单核cpu在任何时间点上,只能运行一个进程,宏观并行、微观串行
进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位
线程
线程,又称轻量级进程(Light Weight Process)程序中的一个顺序控制流程,同时也是CPU的基本调度单位进程由多个线程组成,彼此间完成不同的工作,交替执行,称为多线程
线程的组成
CPU时间片:操作系统(OS)会为每个线程分配执行时间
运行数据:堆空间共享,栈空间独立
堆空间:存储线程需使用的多个对象,多个线程可以共享堆空间的对象
栈空间:存储线程需使用的局部变量,每个线程都拥有独立的栈
线程的逻辑代码
创建线程
第一种1.继承Thread类2.覆盖run()方法3.创建子类对象4.调用start()方法
第二种1.实现Runnable接口2.覆盖run()方法3.创建实现类对象4.创建线程对象,将实现类对象付给线程对象5.调用start()方法
线程的状态
初级
常见的方法
休眠public static void sleep(long millis)当前线程主动休眠millis秒
放弃public static void yield()当前线程主动放弃时间片,回到就绪状态,竞争下一次时间片
结合public final void join()允许其他线程加入到当前线程中(等加入的线程执行完,此线程才继续执行)
线程的 sleep()方法和 yield()方法有什么区别?(1) sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;(2) 线程执行 sleep()方法后转入阻塞(blocked)状态,而执行 yield()方法后转入就绪(ready)状态;(3)sleep()方法声明抛出 InterruptedException,而 yield()方法没有声明任何异常;(4)sleep()方法比 yield()方法(跟操作系统 CPU 调度相关)具有更好的可移植性,通常不建议使用yield()方法来控制并发线程的执行。
线程的安全问题
当多线程并发访问临界资源时,如果破坏原子操作,可能会造成数据不一致
临界资源:共享资源(同一对象),一次仅允许一个线程使用,才可保证其正确性
原子操作:不可分割的多步操作,被视作一个整体,其顺序和步骤不可打乱或缺省
同步方法
第一种同步代码块:synchronized(临界资源对象){//对临界资源对象加锁 //代码(原子操作)}
注:每个对象都有一个互斥锁标记,用来分配给线程的。只有拥有对象互斥锁标记的线程,才能进入对该对象加锁的同步代码块。线程退出同步代码块时,会释放相应的互斥锁标记
第二种同步方法:synchronized 返回值类型 方法名称(参数列表){ //原子操作}
同步规则
只有在调用包含同步代码块的方法或者是同步方法时,才需要对象的锁标记
如果调用的是不包含同步代码块的方法或是普通方法时,则不需要锁标记,直接调用
已知线程安全的内容:StringBuffer、Vector、Hashtable
死锁、生产者与消费者
死锁是指两个或两个以上的进程(线程)在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程(线程)称为死锁进程(线程)。
多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
形成死锁的四个必要条件是什么
互斥条件:线程(进程)对于所分配到的资源具有排它性,即一个资源只能被一个线程(进程)占用,直到被该线程(进程)释放请求与保持条件:一个线程(进程)因请求被占用资源而发生阻塞时,对已获得的资源保持不放。不剥夺条件:线程(进程)已获得的资源在末使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。循环等待条件:当发生死锁时,所等待的线程(进程)必定会形成一个环路(类似于死循环),造成永久阻塞
线程通信
等待
对象.wait();
必须在对obj(对象)加锁的同步代码块(或同步方法)中,在一个线程执行期间,调用了obj.wait(),该线程会释放所拥有的锁标记。同时,进入到obj的等待队列中,等待唤醒
通知(唤醒)
对象.notify();、notifyAll();
必须在对obj加锁的同步代码块(或同步方法)中,从obj的Waiting(等待队列)中随机释放一个或全部线程,对自身线程无影响。
如何停止一个正在运行的线程?在java中有以下3种方法可以终止正在运行的线程:
使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。使用stop方法强行终止,但是不推荐这个方法,因为stop和suspend及resume一样都是过期作废的方法。使用interrupt方法中断线程。
Java 中 interrupted 和 isInterrupted 方法的区别?
interrupt:用于中断线程。调用该方法的线程的状态为将被置为”中断”状态。注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出interruptedException 的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。
interrupted:是静态方法,查看当前中断信号是true还是false并且清除中断信号。如果一个线程被中断了,第一次调用 interrupted 则返回 true,第二次和后面的就返回 false 了。isInterrupted:查看当前中断信号是true还是false
高级多线程
Executor
线程池概念
现有问题
线程是宝贵的内存资源、单个线程约占1MB的空间,过多分配易造成内存溢出
频繁的创建及销毁线程会增加虚拟机回收频率、资源开销,造成程序性能下降
线程池
线程容器,可设定线程分配的数量上限
将预先创建的线程对象存入池中,并重用线程池中的线程对象
避免频繁的创建和销毁
获取线程池
位置:java.util.concurrent
Executor:线程池的顶级接口
ExecutorService:线程池接口,可通过submit(Runnable task)提交任务代码
Executors工厂类:通过此类可以获得一个线程池
ExecutorService es = Executors.newFixedThreadPool(int nThreads)获得一个固定数量的线程池
ExecutorService es = Executors.newCachedThreadPool()获得一个动态数量的线程池,如不够则创建新的,没有上限
Callable接口
public interface Callable<V>{ public void call()throws Exception;}
JDK5加入,与Runnable接口类似,实现之后代表一个线程任务。Callable具有泛型返回值、可以声明异常
Future接口
概念:异步接收ExecutorService.submit()所返回的状态结果,当中包含了call()的返回值
方法:Future f = ExecutorService.submit(task);V get()以阻塞形式等待Future中的异步处理结果(call()的返回值)<V> 数据名称 = f.get();
Callable中泛型的类型是什么就会返回什么类型的返回值,而Future就会接收什么类型的值,就只能建立这种类型的变量
同步与异步
同步:当一个同步调用发出去后,调用者要一直等待调用结果的返回后,才能进行后续的操作
异步;当一个异步调用发出去后,调用者不用管被调用方法是否完成,都会继续执行后面的代码。 异步调用,要想获得结果,一般有两种方式:
主动轮询异步调用的结果;
被调用方通过callback来通知调用方调用结果;
Lock接口
JDK5加入,与synchronized比较,显示定义,结构更灵活提供更多实用性方法,功能更强大、性能更优越
Lock l = New ReentrantLook();
方法:
void lock()获取锁,如锁被占用,则等待
void unlock()释放锁
boolean tryLock()尝试获取锁(成功返回true,失败返回false,不阻塞)
读写锁
ReentrantReadWtiteLock;
ReentrantReadWtiteLock rrwl = new ReentrantReadWtiteLock();ReadLock read = rrwl.readLock();//读锁\tWriteLock write = rrwl.writeLock();//写锁
一种支持一些多读的同步锁,读写分离,可别分配读锁、写锁。
支持多次分配读锁,使多个读操作可以并发执行
互斥规则
写-写:互斥,阻塞。
读-写:互斥,读阻塞写、写阻塞读
读-读:不互斥、不阻塞
在读操作远远高于写操作的环境中,可在保证线程安全的情况下,提高运行效率
在读中加Read锁进入的时候只会获得一次锁,大大降低使用时间,增加效率
线程安全的集合
Collections中的工具方法(获得线程安全集合)
public static <T> Collection<T> synchronizedCollection(Collection<T> c)(获得一个Collection安全集合)
public static <T> List<T> synchronizedList(List<T> list)(获得一个List安全集合)
创建方式List<String> li = new ArrayList<String>(); \t\tList<String> list = Collections.synchronizedList(li);
返回一个新的List类型的集合对象public static <T> List<T> synchronizedList(List<T> list) { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : new SynchronizedList<>(list));}
子类构造方法SynchronizedList(List<E> list) { super(list); this.list = list; }
父类构造方法SynchronizedCollection(Collection<E> c) { this.c = Objects.requireNonNull(c);//非空判断 mutex = this; }final Object mutexfinal Collection<E> c
用Final Object mutex作为同步代码块的对象,进行加锁,保证线程安全public boolean add(E e) { synchronized (mutex) {return c.add(e);} }
public static <T> Set<T> synchronizedSet(Set<T> s)(获得一个Set安全集合)
public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
JDK1.2提供,接口统一、维护性高,但性能没有提升,均以synchronized实现
CopyOnWtiteArrayList
线程安全的ArrayList,加强版读写分离
写有锁,读无锁,读写之间不阻塞,优于读写锁
写入时,先copy一个容器副本、在添加新元素,最后替换引用
使用方式与ArrayList无异List<String> list = new CopyOnWriteArrayList<String>();
写有锁都将底层数组做了一次复制,写的是新数组,完成赋值后,再将新数组替换掉旧数组!每调用一次,底层方法扩容一次!public boolean add(E e) { final ReentrantLock lock = this.lock;//将原来建好的锁赋值给变量, lock.lock(); //获取锁 相当于建了一个新锁 try { Object[] elements = getArray();//获得一个数组 int len = elements.length;font color=\"#9f8759\
private transient volatile Object[] array;
final Object[] getArray() { return array; }返回一个存好array数组
final void setArray(Object[] a) { array = a; }将传过来的数组存入array
final Object[] getArray() {return array;}返回一个array数组
CopyOnWtiteArraySet
线程安全的Set,底层使用CopyOnWriteArrayList实现
唯一不同在于,使用addIfAbsent()添加元素,会遍历数组
public boolean add(E e) { return al.addIfAbsent(e); }//调用CopyOnWriteArrayList下的addIfAbsent()方法
public boolean addIfAbsent(E e) { Object[] snapshot = getArray();//e插入的值,snapshot数组 return font color=\"#c41230\
font color=\"#c41230\
如存在元素,则不添加(扔掉副本)
Set<String> set = new CopyOnWriteArraySet<String>();
ConcurrentHashMap
1.7版本
初始容量默认为16段(Segment),使用分段锁设计
不对整个Map加锁,而是为每个Segment加锁
当多个对象存入同一个Segment时,才需要互斥
最理想的状态为16个对象分别存入16个Segment,并行数量16
使用方式与HashMap无异
只有16把锁,后续扩容之后也只有16把锁,一个锁锁多个链表数组(与1.8比较)
1.8版本
CAS(ComparableAndSwap)交换算法和同步锁
CAS(ComparableAndSwap)交换算法V:要更新的值E:预期的值N:新值当V == E时,V == N
如果在修改过程中,V已经发生变化,V != E ,则取消当前赋值操作,做下一次赋值操作多线程访问,一个线程在修改过程中,时间片没了,下一个线程也去修改完成,上一个线程分到时间片发现V已经发生变化
同步锁锁的是表头对象,拿到锁的对象要先做节点遍历。查看有没有相同的key,相同覆盖,不同,则挂在最后一个节点的next上每个链表的第一个都是表头,都有锁,创建新的也是会有(和1.7不同之处)
synchronized (f) {font color=\"#c41230\
Queue接口(队列)
Collection的子接口,表示队列FIFO(First In First Out)
常用方法
会抛出异常
boolean add(E e)//顺序添加一个元素(到达上限后,在添加则会抛出异常)
E remove() //获得第一个元素并移除(如果队列没有元素时,则抛异常)
E element() //获得一个元素但不移除(如果队列中没有元素时,则抛异常)
返回特殊值:推荐使用
boolean offer(E e)//顺序添加一个元素(到达上限后,在添加则会返回false)
E pool() //获得第一个元素并移除(如果队列没有元素时,则返回null)
E peek() //获得一个元素但不移除(如果队列中没有元素时,则返回null)
子接口ConcurrentLinkedQueue(安全版本Linked队列)
线程安全、可高效读写的队列,高并发下性能最好的队列
linkedList的三种形式
列表(尾部添加,指定下标)
add()
链表(头尾相加)
addfirst
addlost
队列(FIFO)
offer
peek
poll
V:要更新的变量、E:预期值、N:新值
只有当V == E时,V = N;否则表示已被更新过,则取消当前操作
Queue<String> queue = new ConcurrentLinkedQueue<String>();
Queue<String> qu = new Linked<String>();可以只使用队列的方法,但是不安全
子接口BlockingQueue接口(阻塞队列)
Queue的子接口,阻塞的队列,增加了两个线程状态为无限期等待的方法
void put(E e)//将指定元素插入此队列中,如果没有可用空间,则等待
E take()//获取并移除此队列头部元素,如果没有可用元素,则等待
用于解决生产者、消费者问题
ArrayBlockingQueue:数组结构实现,有界队列(手工固定上限)BlockingQueue<String> abq = new ArrayBlockingQueue<String>(10)
LinkedBlockingQueue:链表结构实现,无界队列。(默认上限Integer.MAX_VALUE)BlockingQueue<String> lbq = new LinkedBlockingQueue<String>();
补充知识
用户 (User) 线程:运行在前台,执行具体的任务,如程序的主线程、连接网络的子线程等都是用户线程守护 (Daemon) 线程:运行在后台,为其他前台线程服务。也可以说守护线程是 JVM 中非守护线程的 “佣人”。一旦所有用户线程都结束运行,守护线程会随 JVM 一起结束工作
IO框架
概念:内存与存储设备之间传输数据的通道
流的分类
按方向
输入流:将<存储设备>中的内容读入到<内存>中
输出流:将<内存>中的内容写入到<存储设备>中
按单位
字节流:以字节为单位,可以读写所有数据
字符流:以字符为单位,只能读写文本数据
按功能
节点流:具有实际传输数据的读写功能
过滤流:在节点流的基础之上增强功能
字节流
字节流的父类(抽象类)
InputStream:字节输入流
public int read(){}
public int read(byte[] b){}
OutoutStream:字节输出流
public void write(){}
public void write(byte[] b){}
字节节点流
FileInputStream
从流中读取多个字节,将读到内容存到b数组,返回实际读到的字节数;如过达到文件的尾部,则返回-1
//将指定图片,上传一份到项目里来!\t\t\t\t//文件是在存储设备中的---》读到程序中来---->写入到存储设备中\t\t\t\t//输入流\t\t\t\tFileInputStream fis = new FileInputStream(\"C:\\\\Users\\\\Lenovo\\\\Desktop\\\\1570252842407.jpg\");\t\t\t\t//输出流\t\t\t\tFileOutputStream fos = new FileOutputStream(\"messi.jpg\");\t\t\t\t//缓冲空间过大过小都容易有小问题\t\t\t\tint len = 0;//代表每次读到的字节\t\t\t\twhile((len = fis.read())!=-1) {//只要不读到-1\t\t\t\t\t\tfos.write(len);//读多少 写多少\t\t\t\t\t}\t\t\t\t//释放资源!\t\t\t\tfis.close();\t\t\t\tfos.close();\t\t\t}\t\t}
FileOutputStream
一次写多个字节,将b数组中所有字节,写入输出流
字节过滤流
缓冲流:
分类
BufferedInputStream
BufferedOutoutStream(主要用于BufferedOutoutStream)
FileOutputStream fos = new FileOutputStream(\"文件名\");BufferedOutoutStream bos = new BufferedOutoutStream(fos);
作用
提高IO效率,减少访问磁盘的次数
数据存储在缓存区中,flush是将缓存区的内容写入文件中,也可以直接close
对象流
ObjectOutputStream
ObjectInputStream
功能
增强的缓冲区功能
增强了读写8种基本数据类型和字符串功能
增强了读写对象的功能
readObject()从流中读取一个对象
writeObject(object obj)向流中写入一个对象
使用流传输的对象的过程称为序列化、反序列化
再读取对象的过程中,因为不知道最后一个对象是否在哪一个,如果访问到不在的对象会报错,所以采用try{}catch{}解决
while(true){\t\t\ttry {\t\t\t\tObject obj = ois.readObject();\t\t\t\tSystem.out.println(obj);\t\t\t} catch (Exception e) {\t\t\t\tbreak;//当遇到查询不到对象报 异常时捕获结束循环\t\t\t}\t\t}
对象序列化
必须实现Serializable接口
必须保证其所有属性均可序列化(所有属性实现Serializable接口)
transient修饰为临时属性,不参与序列化
读取到文件尾部的标志:java.io.EOFException
字符流
字符编码
UTF-8
针对Unicode的可变长度字符编码
GB2312
简体中文
GBK
简体中文、扩充
BIG5
台湾、繁体中文
ISO-8859-1
收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、稀薄来语对应得文字符号
当编码方式和解码方式不一致时,会出现乱码
父类
Reader:字符输入流
Writer:字符输入流
字符节点流
FileWriter
public void writr(String str)
FileReader
public int read(char[] c)
一次写多个字符
从流中读取多个字符,返回实际读到的字符数,如过达到文件的尾部,则返回-1用char数组来接收,遍历循环数组,如果结果为-1时break;
字符过滤流
BufferedWriter
支持换行符:newLine()
BufferedReader
PrintWriter
封装了print()/println()方法,支持写入后换行
不足:每次换行都要书写一遍,代码冗余
每读一次读一行:readLine();
while(true) {\t\t\t\t\tString s = br.readLine();\t\t\t\t\tif(s == null) {\t\t\t\t\t\tbreak;\t\t\t\t\t}\t\t\t\t\tSystem.out.println(s);\t\t\t\t}
当使用print()不会换行
桥转换流
InputStreamReader/OutputStreamWriter
可将字节流转化为字符流
可设置字符的编码方式
书写方式
//1.字节输出流\t\t\t\tOutputStream os = new FileOutputStream(\"Files\\\\convert.txt\
//1.字节输入流\t\t\t\tInputStream is = new FileInputStream(\"Files\\\\convert.txt\
读入方式while(true) {\t\t\t\t\tString s = br.readLine();\t\t\t\t\tif(s == null) {\t\t\t\t\t\tbreak;\t\t\t\t\t}\t\t\t\t\tSystem.out.println(s);\t\t\t\t}\t\t\t\tbr.close();
File类
概念:代表物理盘符中的一个文件或则文件夹
File file = new File(\"文件名\");
能不能
boolean file.canExecute()所有可以打开的文件或文件夹,都是可执行的!
boolean file.canWrite() 能不能修改文件(如果文件改为只读,返回false)
boolean file.canRead()能不能执行文件(文件改为隐藏也返回true)
创建和删除
file.mkdirs()如果文件夹不存在会建立一个新的文件夹(只会建文件夹)
file.createNewFile()如果不存在就创建一个文件,如果存在,就返回false
file.delete()如果文件存在,则删除,返回true
file.deleteOnExit();//JVM终止时,执行删除文件
获得
file.getAbsolutePath()获得绝对路径
file.getPath()获得相对路径
file.getName()获得文件名 名字.后缀
file.getFreeSpace() / 1024 / 1024/ 1024//获取硬盘的空闲空间
file.getTotalSpace()/1024 / 1024 / 1024//获取硬盘总空间
file.getParent()获取指定文件的上一级目录
(System.currentTimeMillis() - file.lastModified()) / 1000 / 60获取文件最后一次修改的时间
file.length()获得文件内容的字节
判断
file.isDirectory()判断是否为文件夹
file.isFile()判断是否为文件
file.isHidden()判断文件是否为隐藏
file.exists()判断文件是否存在
FileFilter接口
public interface FileFilter{ boolean accept(File pathname)}
当调用File类中的listFile()方法时,支持传入FileFilter接口接口实现类,对获取文件进行过滤,只有满足条件的文件才可以出现在listFiles()的返回值中
class MyFilter implements FileFilter{\tpublic boolean accept(File pathname) {//true就保存,false就过滤\t\tif(pathname.isFile()) {\t\t\tif(pathname.getName().endsWith(\".doc\")) {\t\t\t\treturn true;//保存\t\t\t}\t\t}\t\treturn false;//过滤\t}}
网络编程
计算机网络
为实现资源共享和信息传递,通过通信线路连接起来的若干主机(Host)
互联网:(Internet)点与点相连
万维网:(WWW - World wide web)端与端相连
物联网:(IoT - Internet of things)物与物相连
网络编程:让计算机与计算机之间建立连接、进行通信
网络模型
OSI(Oper System Ineterconnection)开放式系统互联
第一层:物理层为设备之间的数据通信提供传输信号和物理介质。(双绞线、 光导纤维)
第二层:链路层在物理层上,通过规程或协议(差错控制)来控制传输数据的正确性。(MAC)
第三层:网络层负责定义了能够标识所有网络节点的逻辑地址。(IP地址)
第四层:传输层负责是否选择差错恢复协议、数据流重用、错误顺序重排。(TCP、 UDP)
第五层:会话层负责使应用建立和维持会话,使通信在失效时继续恢复通信。(断点续传)
第六层:表示层负责定义转换数据格式及加密,允许选择以二进制或ASCII格式传输。
第七层:应用层负责文件访问和管理、可靠运输服务、远程操作服务。(HTTP、FTP、SMTP)
TCP/IP模型
一组用于实现网络互连的通讯协议,将协议分为4个层次
第一层按口层负责建文电路连接,是整个同格的物用基础, 典型的协议包括以太网、ADSI等等。
第二层:网络层负责分配地址和传送进制数据, 主要协议是IP协议。
第三层:传输层负责传送文本数据,主要协议是TCP、 UDP协议。
第四层:应用层负责传送各种最终形态的数据,是直接与用户打交道的层,典型协议是HTTP、FTP等。
TCP/UCD
TCP协议: Transmission Control Protocol传输控制协议
是一种面向连接的、可靠的、基于字节流的传输层通信协议。数据大小无限制。建立连接的过程需要三次握手,断开连接的过程需要四次挥手。
UDP协议: User Datagram Protocol用户数据报协议
是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,每个包的大小64KB。
IP
IP协议: Internet Protocol Address互联网协议地址/网际协议地址●分配给互联网设备的数字标签(唯标识)
IP地址分为两种:
IPV4: 4字节32位整数,并分成4段8位的二进制数,每8位之间用圆点隔开,每8位整数可以转换为一一个0~255的十进制整数。 格式: D.D.D.D例如: 255.255.255.255
●A类:政府机构,1.0.0.1 ~ 126.255.255.254
●B类:中型企业,128.0.0.1 ~ 191.255.255.254
●C类:个人用户,192.0.0.1 ~ 223.255.255.254
●D类:用于组播,224.0.0.1 ~ 239.255.255.254
●E类:用于实验,240.0.0.1 ~ 255.255.255.254
●测试IP命令: ping D.D.D.D
●IPV6: 16字节128位整数,并分成8段十六进制数,每16位之间用圆点隔开,每16位整数可以转换为一个0~65535的十进制数。格式: X.X.X.X.X.X.X.X例如: FFFF.FFFF.FFFF.FFFF.FFFF.FFF.FFFF.FFFF
Port
●端口号:在通信实体上进行网络通讯的程序的唯一 标识。
●端口分类
公认端口: 0~1023
●注册端口: 1024~49151
●动态或私有端口: 49152~65535
.常用端口:
●MySql: 3306
●. Oracle: 1521
●Tomcat: 8080
●SMTP: 25
Web服务器: 80
FTP服务器: 21
InetAddress类
概念: 表示互联网协议(P)地址对象,封装了与该P地址相关的所有信息,并提供获取信息的常用方法。
public static InetAddress getLocalHost()获得本地主机地址对象
public static InetAddress getByName(String host)根据主机名称获得地址对象
public static InetAddress[ ]getAllByName(String host)获得所有相关地址对象
public String getHostAddress()获取IP地址字符串
public String getHostName()获得IP地址主机名
cmd获得本机ip ipconfig
基于Tcp的网络编程
Socket编程
客户端Socket
服务器ServerSocket
通信要求:IP地址+端口号
Socket(套接字)是网络中的一个通信节点
开发步骤
客户端
Socket client = new Socket(\"192.168.1.104\
服务器
ServerSocket server = new ServerSocket(5555);//创建ServerSocket,指定端口号Socket client = server.accept();//调用accept等待客户端接入InputStream is = client.getInputStream();font color=\"#f1753f\
Properties集合添加
Properties userPros = new Properties();
//1将集合加载到文件中去\t\t\t\tuserPros.store(new FileWriter(\"Files\\\\userPros.properties\
userPros = new Properties();\t\t//指向信息配置文件\t\tFile file = new File(\"Files\\\\userPros.properties\");\t\tif(file.exists()) {//文件存在\t\t\ttry {\t\t\t\t//把properties文件里的内容通过字符流加载到properties集合里\t\t\t\tuserPros.load(new FileReader(file));\t\t\t} catch (Exception e) {\t\t\t\te.printStackTrace();\t\t\t} \t\t}
反射
类对象
区别
类的对象:基于某个类new出来的对象,也称为实例对象
类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)
获取类对象
通过类的对象,获取类对象Student s = new Student();Class c = s.getClass();
通过类名获取类对象Class c = 类名.class;
通过静态方法获取类对象Class c = Class.forName(\"包名.类名\");
//获得指定类对象的包\t\tPackage pack = c.getPackage();
//获得父类的Class对象\t\tClass superClass = c.getSuperclass();
//获得接口的Class对象\t\tClass[] interfaces = c.getInterfaces();
//获取属性(自身+父类的公开属性)\t\tField[] fields = c.getFields();
//获取方法(自身+父类的所有公开方法)\t\tMethod[] methods = c.getMethods();
//获得Class对象的自身所有属性\t\tField[] fields2 = c.getDeclaredFields();
//获得自身的全部方法Method[] methods2 = c.getDeclaredMethods();
//获得构造方法的形参Constructor[] cs = c.getConstructors();//先获得全部构造方法 for(Constructor ct : cs) { System.out.print(ct.getName()+\":\"); Class[] param = ct.getParameterTypes();//通过构造方法获得参数 for(Class p : param) { System.out.println(p.getName()); }\t\t}
工厂设计模式
开发中有一个非常重要的原则“开闭原则”,对拓展开放、对修改关闭。
工厂模式主要负责对象创建的问题
可通过反射进行工厂模式的设计,完成动态的对象创建。
创建对象的两种方式(以Student为例)
Student s = new Student();
Class c = Student.class;Object o = c.newInstance();Student s2 = (Student)o;
//通过输入流获取全限定名\t\tFileReader fr = new FileReader(\"Files\\\\properties.txt\");\t\tBufferedReader br = new BufferedReader(fr);\t\tString str = br.readLine();\t\tObject oo = createObject(str);
//创建对象!\t//工厂:创建对象工厂public static Object createObject(String str){ try { Class c = Class.forName(str); Object o = c.newInstance(); return o;//通过一系列的转换返回一个Object对象 } catch (Exception e) { e.printStackTrace(); } return null;\t}
invoke
一:通过Class类对象去调用对象的方法
//反射 类的对象\t\tObject o = createObject(\"com.qf.day35.t1.reflects.Student\");\t\t//类对象\t\tClass c =o.getClass();font color=\"#00a650\
//注意:反射是一种Java底层技术,可以取消语言检查。 突破封装\t\tm4.setAccessible(true);font color=\"#f1753f\
二:通过方法输入对象,形参类型和实参
Object o = TestInvoke.createObject(\"com.qf.day35.t0.invoke.Student\");font color=\"#c41230\
单例模式
只允许创建一个该类的对象
饿汉式:天生线程安全(无锁)、类加载时创建(不用的时候,也被迫创建了,占用资源)
class Singleton{private static final Singleton instance = new Singleton();//私有静态常量private Singleton() {}//私有构造方法public static Singleton getInstance() {//通过调用静态方法创建对象 return instance; }}
懒汉式:使用时创建、天生线程不安全(加同步锁); 效率低
class Singleton{private static Singleton instance = null;//私有静态最初为nullprivate Singleton() {}//私有构造方法public synchronized static Singleton getInstance() { if(instance == null) {//第一次创建时 instance = new Singleton();} return instance;//返回对象}}
懒汉式(加强版):使用时创建、天生线程安全
class Singleton{\tprivate Singleton() {}\tprivate static class Holder{//私有内部类\t\tstatic final Singleton instance= new Singleton(); \t}\t\tpublic static Singleton getInstance() {\t\treturn Holder.instance;//调用私有内部类\t}}
JDK8
Lambda表达式
概念:允许把函数作为一个方法的参数(函数作为参数传递到方法中)
函数式接口 变量名 = (参数1,参数2)->{ //方法体}
注意事项
形参列表的数据类型会自动判断
如果形参列表为空,只需保留()
如果形参只有一个,()可以省略,只要参数名字即可
如果执行语句只有一句,且无返回值,{}可以省略
若有返回值,仍想省略{},return也省略。保证执行语句只有一句
lambda表达式不会生成单独的内部类文件
lambda访问局部变量时,变量要修饰final,如果没加,会自动添加。
用lamada表达式启动线程
//第一种方式建立内部类\t\tnew Thread(){\t\t\tpublic void run() {\t\t\t\tSystem.out.println(\"子线程启动\");\t\t\t}\t\t}.start();
//第二种方式,用lambda表达式\t\tRunnable r = ()->{System.out.println(\"第二个子线程启动\");};\t\tnew Thread(r).start();
//第三种,lambda表达式简写\t\tnew Thread( ()->System.out.println(\"第三个线程\") ).start();
函数式接口
如果一个接口只有一个抽象方法,则该接口称为函数式接口
为了保证接口达到要求,可以添加@FunctionalInterface注解
四个核心函数式接口
Consumer<T>消费型接口 void accept(T t)
接收一个参数,不返回
第一种:通过自己写表达式,自己调自己Consumer<String> cs = (e)->System.out.println(\"今天天气:\" + e);\t\tcs.accept(\"晴\");
第二种:通过方法形参中写函数型接口,调用时写Lambda表达式font color=\"#f68b1f\
Supplier<T> 供给型接口 T get();
不接收参数,返回
第一种:自己写,自己调Supplier<Integer> sp = ()->new Random().nextInt(200);\t\tint nums = sp.get();\t\tSystem.out.println(nums);
第二种:调方法()font color=\"#f1753f\
接收一个参数,返回
font color=\"#00a650\
第二种:调方法;b style=\
Predicate<T> 断言型接口 boolean test(T t);
接收一个参数,返回boolean类型的判断
List li = new ArrayList();\t\tli.add(\"光芒\");\t\tli.add(\"公民\");\t\tli.add(\"阿杰\");\t\tli.add(\"阿辉\");
第一种:自己写自己调Predicate<String> pd = (e)->e.startsWith(\"阿\");\t\tList<String> newli = new ArrayList<String>();\t\tfor (String str : li) {\t\t\tif(pd.test(str)){\t\t\t\tnewli.add(str);\t\t\t}\t\t}
第二种:传一个集合,调方法font color=\"#f1753f\
方法引用
方法引用是Lambda表达式的一种简写形式,如果Lambda表达式方法体中只是调用一个特定的已存在的方法,则可以使用方法引用
使用::操作符将对象或类的方法名的名字分割开来
对象::实例方法
Consumer c = (e)->System.out.println(e);\t\tc.accept(\"nihao\");//Lambda表达式\t\tConsumer c2 = System.out::println;\t\tc2.accept(\"你好啊\");//方法引用
Employee emp = new Employee(\"阿杰\
类::静态方法(不常用)
font color=\"#f68b1f\
方法引用:Comparator<Integer> com2 = Integer::compare;TreeSet<Integer> ts = new TreeSet<Integer>(com2);
类::实例方法
类::new
Lambda表达式Supplier<Employee> supp = ()->new Employee();\t\tEmployee emps = supp.get();
方法引用:Supplier<Employee> supp2 = Employee::new;\t\tEmployee emps2 = supp2.get();
注意:调用的方法参数列表与返回值类型,要与函数型接口中的方法参数列表与返回值类型一致
Stream API
Stream是Java8中处理数组、集合的抽象概念
可以执行非常复杂的查找、过滤、映射等操作
中间操作
System.out.println(\"------------filter-----------------------\");过滤\t\tli.stream().filter((e)->e.getName().startsWith(\"阿\")).forEach(System.out::println);
System.out.println(\"------------limit-----------------------\");截断,不超过给定数量\t\tli.stream().limit(3).forEach(System.out::println);
System.out.println(\"------------distinct-----------------------\");筛选,利用hashCode和equals\t\tli.stream().distinct().forEach(System.out::println);
System.out.println(\"------------map-----------------------\");//将一个类型转换一个类型\t\tli.stream().map((e)->e.getName()).forEach(System.out::println);\t\tli.stream().map((e)->e.getAge()).forEach(System.out::println);\t\tList<String> newLi = Arrays.asList(\"aaa\
System.out.println(\"------------sorted-----------------------\");自然排序\t\tnewLi.stream().sorted().forEach(System.out::println);\t\tli.stream().sorted().forEach(System.out::println);
要求传入的参数是实现了Comparable接口
System.out.println(\"--------sorted(Comparator)--------\");font color=\"#662c90\
终止操作
System.out.println(\"---------------------count-------------------\");返回流中元素的总个数\t\tlong l = li.stream().count();
System.out.println(\"---------------------anyMatch---------------------------\");是否有匹配的\t\tboolean boo = li.stream().filter((e)->e.getName().length()>= 3).anyMatch((e)->e.getName().startsWith(\"阿\"));
System.out.println(\"---------------------allMatch---------------------------\");是否全部都匹配\t\tboolean boo2 = li.stream().filter((e)->e.getName().length()>=3).allMatch((e)->e.getName().startsWith(\"阿\"));
System.out.println(\"---------------------noneMatch---------------------------\");是否没有匹配的\t\tboolean boo3 = li.stream().filter((e)->e.getName().length()>=3).noneMatch((e)->e.getAge()>= 30);
System.out.println(\"---------------------findFirst---------------------------\");返回第一个\t\tOptional<Employee> o = li.stream().findFirst();\t\tSystem.out.println(o.get());
System.out.println(\"---------------------findAny---------------------------\");返回任意\t\tOptional<Employee> o2 = li.stream().filter((e)->e.getName().length()>=3).findAny();\t\tSystem.out.println(o2.get());
System.out.println(\"---------------------Max---------------------------\
System.out.println(\"---------------------Min---------------------------\");font color=\"#c41230\
stream()
//串行-->一条执行路径 单线程
parallelStream()
//并行-->多条执行路径, 多线程
0 条评论
回复 删除
下一页