Skip to content
0

文章发布较早,内容可能过时,阅读注意甄别。

Java学习笔记

参考链接:学习笔记:黑马程序员Java-基础篇(第一部分)-CSDN博客

1 Java安装

1.1 JDK安装

需要安装JDK(Java Development Kit : Java开发者工具包)Oracle 官网下载JDK

推荐下载,LTS:long-term support 长期支持版(JDK 8 、11、17、21)

1.2 JDK的组成

  • JVM (Java Virtual Machine): Java虚拟机,真正运行Java程序的地方。
  • 核心类库:Java自己写好的程序,给程序员自己的程序调用的。
  • JRE (Java Runtime Environment): Java 的运行环境。
  • JDK (Java Development Kit):Java开发工具包 (包括上面所有)。

1.3 配置JDK的环境变量

  • 目前较新的JDk在安装时,会自动配置javac、java程序的路径到Path环境变量中。
  • 较老版本的JDK不会自动配置,需要手动配置
  • 建议为JDK再配置JAVA_ HOME环境变量

JAVA_HOME:是用于告诉操作系统JDK安装在了哪个位置(将来其他技术要通过这个环境变量找JDK)

例如:JAVA* HOME D:\develop\java \jdk-21 Path %JAVA* HOME%\bin

1.4 Java编译解释

1、打开命令行,切换到有java文件的路径

2、运行javac <文件名>.java, 可以生成<文件名>.class文件

3、运行java <类名>,运行java程序(必须与代码里所谓的类名称一致)

1.5 IDEA开发

步骤:

  • project -> module -> package -> class
  • 一个project中可以创建多个module
  • 一个module中可以创建多个package
  • 一个package中可以创建多个class

2 Java基础语法

Java功能的最小单元:方法

2.1 Java注释

  • 单行注释
java
// 注释内容,只能写一行
  • 多行注释
java
/*
	注释内容1
	注释内容2
*/
  • 文档注释:
java
/**
	注释内容
	注释内容
*/

2.2 关键字

2.2.1 概述

Java关键字就是被Java赋予了特定含义的英文单词。当我们在代码中写了关键字之后,程序在运行的时候,就知道要做什么事情了。

2.2.2 分类

Java 关键字是编程语言中预定义的具有特殊含义的词汇,这些关键字用于控制程序的结构、流程和行为

TIP

修饰符关键字:public、protected、private、static、final、abstract 访问控制关键字:public、protected、private、default(默认) 类、接口和包关键字:、class、interface、enum、package、import、extends、implements 方法关键字:void、return、this、super 流程控制关键字:if、else、switch、case、default、while、do、for、break、continue、return 异常处理关键字:try、catch、finally、throw、throws 逻辑关键字:true、false、null 其他关键字:new、instanceof、synchronized、transient、volatile、assert

2.3 字面量

2.3.1 概述

Java 字面量是程序中直接使用的常量值,它表示各种数据类型的固定值。字面量可以是整数、浮点数、字符、字符串等数据类型的常量值,它们在代码中直接出现,不需要进行计算或转换。

2.3.2 分类

1、整数字面量:表示整数值,可以使用十进制、八进制(以0开头)和十六进制(以0x或0X开头)表示法。例如:42, 012,0xFF

2、浮点数字面量:表示浮点数值,包括普通的浮点数和科学计数法表示。例如:3.14, 2.0e-5

3、字符字面量:表示单个字符,使用单引号括起来。例如:'A', '1', '@''露'

4、字符串字面量:表示一个字符串,使用双引号括起来。例如:"Hello, World!", "Java"

5、布尔字面量:表示布尔值,只有两个取值:truefalse

6、null 字面量:表示空引用,用于表示对象引用不指向任何有效的对象。

7、转义序列:一些特殊的字符序列,以反斜线 \ 开头,用于表示无法直接输入的字符,如换行符

\n、制表符 \t 等。

8、数组字面量:用花括号 {} 表示,用于初始化数组。例如:{1, 2, 3}

9、枚举常量:枚举类型的常量值,表示枚举中的特定选项。

10、字符编码字面量:表示字符的Unicode编码,以 \u 开头,后面跟着四个十六进制数字。例如:\u0041 表示字符 'A'

2.4 数据类型

2.4.1 概述

Java 数据类型是用来定义变量或表达式可以存储的数据类型的分类

2.4.2 分类

2.4.2.1 基本数据类型

1、整数类型(Integer Types)

byte:8位,范围为 -128 到 127、

short:16位,范围为 -32,768 到 32,767、

int:32位,范围为 -2^31 到 2^31 - 1、

long:64位,范围为 -2^63 到 2^63 - 1

2、浮点类型(Floating-Point Types)

float:32位,用于表示单精度浮点数、

double:64位,用于表示双精度浮点数

3、字符类型(Character Type)

char:16位,用于存储一个 Unicode 字符

4、布尔类型(Boolean Type)

boolean:用于表示布尔值,只有两个取值:truefalse

2.4.2.2、引用数据类型

1、类(Class):类是用来创建对象的模板。它定义了对象的属性(成员变量)和方法(成员方法)。通过实例化类,可以创建类的对象,并使用对象调用类的方法。

2、接口(Interface):接口定义了一组方法的规范,但没有实际的方法体。类可以实现一个或多个接口,从而获得接口定义的方法,并在类中实现这些方法。

3、数组(Array):数组是一种用于存储相同类型元素的数据结构。它可以是一维数组或多维数组,用于在内存中连续存储多个元素。

4、枚举(Enum):枚举是一种特殊的类,用于表示一组预定义的常量。枚举常常用于表示一组相关的值。

5、字符串(String):字符串是一种引用数据类型,但它具有特殊的性质,可以像基本数据类型一样进行操作。字符串实际上是一个字符序列,它有许多方法用于处理字符串操作。

6、自定义引用类型:除了上述内置的引用数据类型,开发人员还可以创建自定义的类和接口,以及它们的实例,从而构建更复杂的数据结构和功能。

NOTE

基本数据类型:基本数据类型是按值传递的,它们在Java虚拟机栈中分配内存空间,并直接存储值本身。当基本数据类型的变量被赋值时,实际上是将该变量中的值复制到另一个变量中,这两个变量之间没有任何关联。

引用数据类型:引用数据类型是按引用传递的,它们在Java虚拟机堆中分配内存空间,存储的是对象的引用(内存地址)。当引用数据类型的变量被赋值时,实际上是将该变量中的引用复制到另一个变量中,这两个变量指向同一个对象。

2.4.3 数据类型转换

1、自动类型转换(小-->大)

类型范围小的变量,可以直接赋值给类型范围大的变量。

取值范围关系: byte < short (char) < int < long < float < double

byte、short、char三种类型的数据在运算的时候,都会直接先提升为int,然后再进行运算。

多种混合运算时,先转换成容量最大的再做运算

2、强制类型转换(大-->小)

默认情况下,大范围类型的变量直接赋值给小范围类型的变量会报错! 可以强行将类型范围大的变量、数据赋值给类型范围小的变量

格式:数据类型 变量1= (数据类型)变量2、数据

注意:

  • 可能出现数据丢失,有精度损失。
  • 小数强制转换成整数是直接截断小数保留整数。
  • boolean不能参与类型转换,其他都行

2.5 标识符

在Java中,标识符是用来标识程序中各种元素的名称,比如变量、方法、类、接口等。标识符是由字母、数字、下划线(_)和美元符号($)组成的序列,且必须以字母、下划线或美元符号开头。标识符在编程中用于命名各种实体,使得程序易于阅读、理解和维护

2.5.1 硬性要求

必须要这么做,否则代码会报错。

  • 必须由数字字母下划线_、**美元符号$**组成。
  • 数字不能开头
  • 不能是关键字
  • 区分大小写的。

2.5.2 软性建议

1、小驼峰命名法

适用于变量名和方法名

  • 如果是一个单词,那么全部小写,比如:name
  • 如果是多个单词,那么从第二个单词开始,首字母大写,比如:firstName、maxAge

2、大驼峰命名法

适用于类名

  • 如果是一个单词,那么首字母大写。比如:Demo、Test。
  • 如果是多个单词,那么每一个单词首字母都需要大写。比如:HelloWorld

2.6 权限修饰符

2.6.1 概述

在Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限。

  • public:公共的,所有地方都可以访问。

  • protected:本类 ,本包,其他包中的子类都可以访问。

  • 默认(没有修饰符):本类 ,本包可以访问。注意:默认是空着不写,不是default

  • private:私有的,当前类可以访问。

==public > protected > 默认 > private==

2.6.2 权限访问能力

权限范围:public > protected > 默认 > private

publicprotected默认private
同一类中
同一包中的类
不同包的子类
不同包中的无关类

编写代码时,如果没有特殊的考虑,建议这样使用权限:

  • 成员变量使用private ,隐藏细节。
  • 构造方法使用 public ,方便创建对象。
  • 成员方法使用public ,方便调用方法。

补充:

不加权限修饰符,就是默认权限

2.6.3 权限使用规则

实际开发中,一般只用private和public

  • 成员变量私有
  • 方法公开

注意:

如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有

2.6 方法

2.6.1 概述

方法(method)是程序中最小的执行单元

注意:

  • 方法必须先创建才可以使用,该过程成为方法定义
  • 方法创建后并不是直接可以运行的,需要手动使用后,才执行,该过程成为方法调用

2.6.2 定义和调用

1、方法定义完整格式:

java
修饰符 返回值类型 方法名 (形参列表){
	方法体代码(需要执行的功能代码)
	return 返回值;
}

1、方法调用完整格式:

java
方法名(形参列表)

注意:

  • 方法必须先定义,后调用,否则程序将报错
  • 参数是由数据类型和变量名组成 - 数据类型 变量名 例如:int a
  • 方法定义时,参数中的数据类型与变量名都不能缺少,缺少任意一个程序将报错
  • 方法定义时,多个参数之间使用逗号( ,)分隔
  • 方法调用时,参数的数量与类型必须与方法定义中的设置相匹配,否则程序将报错

2.6.3 方法重载

满足下列条件的多个方法相互构成重载

  • 多个方法在同一个类中
  • 多个方法具有相同的方法名
  • 多个方法的参数列表不同(个数不同或者类型不同或者顺序不同)

TIP

方法重载与方法的返回类型无关

例如,以下不是方法重载,而且报错:

java
public class MethodDemo {
	public static void fn(int a) {
    	//方法体
    }
    public static int fn(int a) { 	/*错误原因:重载与返回值无关*/
    	//方法体
    }
}

2.7 运算符和表达式

1、概述:

Java运算符是用于对一个或多个操作数执行操作的特殊符号

表达式是由变量、常量、运算符和方法调用组成的符合语法规则的语句

运算符和表达式区别:

运算符就是对常量或者变量进行操作的符号

表达式就是符合Java语法的式子就是表达式

2、算术运算符:

定义:算术运算符是用来执行基本的数学运算的

例如:

+、-、 *、  /

3、自增自减运算符:

定义:自增自减运算符是一种特殊的算数运算符,用于对变量的值进行加1或减1操作

例如:

 ++、--

4、赋值运算符:

定义:赋值运算符是Java中用于给变量赋值的运算符

例如:b = 20

5、扩展赋值运算符:

定义:扩展赋值运算符是将算术运算符和赋值运算符组合在一起的运算符

例如: "+="、 "-="、 "*="、 "/="、 "%="

特点:扩展的赋值运算符中隐层还包含了一个==强制转换,==,例如:

a += b; //等价于a = (a的类型)(a + b);

6、关系运算符:

含义:关系运算符是用于比较两个值之间的大小关系

例如:a > b

注意:区分 == 和 = 赋值运算符和关系运算符

7、逻辑运算符:

含义:用于多个布尔表达式组合在一起,以生成新的布尔表达式

例如:true & true、false & false

注意:逻辑运算符还有!、& 、 |、^

8、短路逻辑运算符:

含义:如果已经可以确定整个表达式的结果时,就不再继续计算剩下的表达式

例如:用户名正确 && 密码正确

9、三元运算符:

含义:被称为条件运算符,它是Java中唯一的具有三个操作数的运算符

格式:关系表达式 ? 表达式1 :表达式2 ; 例如:a > b ? a : b

10、运算符优先级:小括号优先( )

11、隐式转换与强制转换

隐式转换:自动类型提升

  • 取值关系:byte < short < int < long < float < double
  • 注意:float类型的存储空间比long类型小,但float类型的表示范围比long类型大

强制转换:强制类型提升

格式:

目标数据类型 变量名 = (目标数据类型)被强转的数据

12、字符串的+操作(特例):

含义:当+操作中出现了字符,会拿着字符到计算机内置的ASCII码表中去查对应的数字,然后再进行计算

例如:

java
char c = 'a';
int result = c + 0;
System.out.println(result);//9

2.8 数组

2.8.1 定义

数组指的是一种容器,可以同来存储同种数据类型的多个值

2.8.2 定义方式

  • 格式一:
java
数据类型 [] 数组名;
//例如
int [] array;
  • 格式二
java
数据类型  数组名 [];
//例如
int array [];
  • 注意:不同的数据类型对应不同的默认值
整数类型:0	小数类型:0.0	布尔类型:false	字符类型:'\u0000'	 引用类型:null

2.8.3 初始化

1、静态数组初始化

  • 格式一:
java
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,元素4...};
//例如
double[] arr = new double[]{1.1,1.2,1.3};
  • 格式二:
java
数据类型[] 数组名 = {元素1,元素2,元素3,元素4...};
//例如
int[] array = {1,2,3,4,5};

2、动态数组初始化

java
数据类型[] 数组名 = new 数据类型[数组的长度];
//例如
double[] arr = new double[10];

区别:

  • 语法不同
  • 数组长度不同
  • 赋值时机不同
  • 注意:无论是何种数组,数组的最大长度为,数组的长度-1。例如:arr.length - 1

2.8.4 地址值

数组的地址值是指向数组对象的指针或引用

例如:

java
int[] arr = {1,2,3,4,5};
System.out.println(arr);	//[I@6d03e736
/*
[ :表示现在打印的是一个数组。
I:表示现在打印的数组是int类型的。
@:仅仅是一个间隔符号而已。
6d03e736:就是数组在内存中真正的地址值。(十六进制的)
*/

2.9 抽象类和接口

2.9.1 抽象类

1、概述:

  • 定义:没有方法体的方法称为抽象方法,包含抽象方法的类就是抽象类
  • 抽象方法:没有方法体的方法
java
// 抽象方法
public abstract void abstractMethod();
  • 抽象类:包含抽象方法的类
java
public abstract class AbstractClass {
    // 抽象方法
    public abstract void abstractMethod();
}

WARNING

注意:抽象类不一定有抽象方法,但是有抽象方法的类必须定义成抽象类。

2、abstract介绍

  • 使用:==被继承==

  • 特征: 1、抽象类得到了拥有抽象方法的能力,也就是说有了自己的一套规范

    2、抽象类失去了创建对象的能力,也就是说不能创建对象

  • 细节:

    • 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象

    • 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的

    • 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类

    • 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通过而报错

    • 抽象类存在的意义是为了被子类继承

  • 意义:抽象类存在的意义是为了被子类继承,否则抽象类将毫无

  • 抽象类和接口区别,主要在于构造函数、成员变量、继承关系(单继承,多实现)

2.9.2 接口

1、概述

  • 含义:接口是一种规范或契约,它只定义了方法签名、常量以及嵌套类型的声明,没有方法实现或属性
  • 格式:
java
//接口的定义格式:
interface 接口名称{
    // 抽象方法
}
// 接口的声明:interface
// 接口名称:首字母大写,满足“驼峰模式”
  • 特点:

    1、抽象方法:会自动加上public abstract修饰

    2、常量:会自动加上 public static final修饰

2、基本实现

  • 实现方式:使用 implements关键字
  • 格式:
java
/**接口的实现:
    在Java中接口是被实现的,实现接口的类称为实现类。
    实现类的格式:*/
class 类名 implements 接口1,接口2,接口3...{
}
  • 要求:接口体现的是一种规范,接口对实现类是一种强制性的约束。需要强制重写或定义为抽象类

3、接口与接口的多继承

  • 含义:一个接口可以继承另一个或多个接口,这被称为接口的多继承
  • 格式:
java
public interface SportMan extends Law , Abc {
    void run();
}

补充:接口和类之间的关系

  • 类和类是继承关系,只能单继承,不能多继承
  • 类与接口是实现关系,可以单实现,还可以多实现
  • 接口与接口是继承关系,可以单继承,还可以多继承

4、JDK中接口新增:

  • JDK7以前:接口中只能定义抽象方法。
  • JDK8以后:新增默认方法(default method)
java
格式:public default 返回值类型 方法名(参数列表) {   }
// 例如
public default void show(){
    System.out.println("InterA接口中的默认方法 ---- show");
}
  • 特点:

    1、默认方法不是抽象方法,所以不强制被重写

    2、解决接口升级的问题

  • 注意:

    1、静态方法只能通过接口名调用,不能通过实现类名或者对象名调用

    2、public可以省略,static不能省略

  • JDK9以后:新增private修饰符 格式:

java
- 格式 : private返回值类型方法名(参数列表){}
- 范例: private void show() { }

- 格式: private static返回值类型方法名(参数列表){}
- 范例: private static void method(){ }

5、接口的多态

  • 含义:当一个方法的==参数是接口==时,可以传递接口所有实现类的对象,这种方式称之为==接口多态==

6、接口的细节

  • 实现类可以同时继承==A类==也可以实现接口,不过需要实现所有方法
  • 实现类可以同时继承==抽象类==也可以实现接口,不过需要重写所有方法
  • 实现类实现了两个接口,且两个接口存在相同抽象方法,此时只需重写==一次==
  • 当实现了接口,子类实现类中的方法跟父类方法同名是,==看需求==选择重写
  • 做空重写:只需要重写实现类中的==部分==接口,可先创建类进行重写,在将此类继承,实现部分

2.9.3 抽象类和接口的异同点

(1)相同点:

  1. 都是抽象形式,都可以有抽象方法,都不能创建对象
  2. 都是派生子类模式:抽象类是被子类继承使用,接口是被实现类实现
  3. 一个继承抽象类或者实现接口,都必须重写它们的抽象方法,否则自己成为抽象类或者报错
  4. 都能支持多态,都能够实现解耦合

(2)不同点

  1. 抽象类中可以定义类的全部普通成员,接口只能定义常量,抽象方法 (JDK8新增的三种方式)
  2. 抽象类只能被类单继承,接口可以被类多实现。
  3. 一个类继承抽象类就不能再继承其他类,一个类实现了接口 (还可以继承其他类或者实现其他接口)。
  4. 抽象类体现模板思想:更利于做父类,实现代码的复用性。 最佳实践
  5. 接口更适合做功能的解耦合:解耦合性更强更灵活。 最佳实践
抽象类接口
方法实现可以有实现的方法和非抽象方法只有方法签名,无方法实现
构造函数可以构造函数法定义构造函数
成员变量可以成员变量只能定义常量,成员变量
继承关系子类只能继承一个抽象类类可以实现多个接
功能实现提供对类的部分实现定义契约和行为规范

2.10 代码块

代码块是类的5大成分之一(成员变量、构造器、方法、代码块、内部类)。 代码块分为两种: 静态代码块: 格式: static {} 特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会执行一次。 作用:完成类的初始化,例如:对静态变量的初始化赋值。

实例代码块: 格式: {} 特点:每次创建对象时,执行实例代码块,并在构造器前执行。 作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量进行初始化赋值。

2.11 Lambda表达式

Lambda表达式: Lambda表达式只能替代函数式接口的匿名内部类

什么是函数式接口? 有且仅有一个抽象方法的接口。 注意:将来我们见到的大部分函数式接口,上面都可能会有一个@Functionallnterface的注解,该注解用于约束当前接口必须是函数式接口。

3 Java高级语法

3.1 集合类

3.1.1 概述

集合分为单列集合与双列集合

单列集合:Collection 双列集合:Map

3.1.2 单列集合

3.1.2.1 List系列集合

特点:有序、可重复、有索引

实现类:

  • ArrayList:底层是基于数组存储数据,查询快,增删慢
  • LinkedList:底层是基于双向链表存储数据,增删相对快,查询慢,首尾操作比较快

用LinkedList实现队列和栈

java
// 队列
LinkedList<String> queue = new LinkedList<>();
queue.addLast("Java");
queue.addLast("C");
queue.addLast("C++");
queue.addLast("Python");
queue.addLast("C#");
System.out.println(queue);  // [Java, C, C++, Python, C#]
System.out.println(queue.removeFirst()); // Java
System.out.println(queue.removeFirst()); // C
System.out.println(queue);  // [C++, Python, C#]
//栈
LinkedList<String> stack = new LinkedList<>();
stack.push("Java");
stack.push("C");
stack.push("C++");
stack.push("Python");
stack.push("C#");
System.out.println(stack);  // [C#, Python, C++, C, Java]
System.out.println(stack.pop());  // C#
System.out.println(stack.pop());  // Python
System.out.println(stack);  // [C++, C, Java]

3.1.3.2 Set系列集合

特点:无序、不可重复、无索引

实现类:

  • HashSet:无序、不可重复、无索引,底层是由JDK8之前:数组、链表,JDK8之后:数组、链表、红黑树组成
  • LinkedHashSet:有序、不可重复、无索引,底层是由数组、链表、红黑树组成,增加双链表添加顺序
  • TreeSet:排序展示(默认按升序排序)、不可重复、无索引

3.1.3 双列集合

3.1.3.1 Map集合

特点:无序、不可重复、无索引

实现类:

  • HashMap:无序、不重复、无索引,基于哈希表实现,底层是由JDK8之前:数组、链表,JDK8之后:数组、链表、红黑树组成,可以存储null键和null值,键相同时会覆盖
  • LinkedHashMap:有序、不重复、无索引,基于哈希表实现,可以存储null键和null值,键相同时会覆盖
  • TreeMap:排序展示(默认按升序排序)、不可重复、无索引,基于红黑树实现,按照键的自然顺序或者自定义的比较器排序,不允许有null键,但可以有null值

HashMap跟HashSet的底层原理是一模一样的,都是基于哈希表实现的。HashSet集合的底层原理就是HashMap。

LinkedHashMap跟LinkedHashSet的底层原理是一模一样的,都是基于哈希表+双向链表实现的,LinkedHashSet集合的底层原理就是LinkedHashMap。

TreeMap 跟TreeSet集合的底层原理是一样的,都是基于红黑树实现的排序。TreeSet集合的底层原理就是TreeMap。

3.2 Stream流

3.2.1 概述

在 Java 8 中,Stream 是一种处理集合的机制,它可以对集合进行各种操作(过滤、映射、排序等)并生成新的集合,同时支持并行处理

作用:结合了Lambda表达式,简化集合、数组的操作

3.2.2 使用步骤

1、获取Stream流对象

  • Collection体系集合:使用默认方法stream()生成流, default Stream stream()
  • Map体系集合:把Map转成Set集合,间接的生成流
  • 数组:通过Arrays工具类中的静态方法stream生成流
  • 同种数据类型的多个零散数据:通过Stream接口的静态方法of(T… values)生成流

2、使用中间方法处理数据

(1)filter过滤

java
list.stream().filter(new Predicate<String>() {
    @Override
    public boolean test(String s) {
        return s.startsWith("张");
    }
})

(2)limit获取前几个元素

java
list.stream().limit(3)

(3)skip跳过前几个元素、

java
list.stream().skip(2)

(4)distinct:元素去重,(注意,当使用自定义对象进行去重时,依赖hashCodeequals方法)

java
list1.stream().distinct()

(5)concat合并a和b两个流为一个

java
Stream.concat(list1.stream(),list2.stream())
//注意:在使用时,此处使用Stream对象中的concat静态方法

(6)map转换流中的数据类型

java
// Function<原本数据类型,需要转换的目标数据类型>
list.stream().map(new Function<String, Integer>() {
    @Override
    public Integer apply(String s) {
        String[] arr = s.split("-");
        String ageString = arr[1];
        int age = Integer.parseInt(ageString);
        return age;
    }
})

3、使用终结方法处理数据

(1)forEach:遍历

java
list.stream().forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        })

(2)count统计

java
list.stream().count();

(3)toArray:收集流中的数据,放到数组中

java
list.stream().toArray(new IntFunction<String[]>() {
    @Override
    public String[] apply(int value) {
        return new String[value];
    }
});

System.out.println(Arrays.toString(arr));

(4)collect:收集流中的数据,放到集合中

java
Map<String, Integer> map = list.stream()
    .filter(s -> "男".equals(s.split("-")[1]))
    .collect(Collectors.toMap(
        new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s.split("-")[0];
            }
        },
        new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.valueOf(s.split("-")[2]);
            }
        }
    ));

3.3 File 文件

3.3.1 概述

  1. 含义:java.io.File 类是文件和目录路径名的抽象表示
  2. 路径:绝对路径和相对路径
  3. 作用:用于操作文件和目录,例如创建删除,获取文件的信息。注意,File类不能获取文件内的详细内容

3.3.2 常用方法

1、判断、获取:isDirectory()、isFIle()、exists()、length()、getAbsolutePath()、getPath()、getName()、lastModified() 2、创建、删除:createNewFile()、mkdir()、mkdirs()、delete()

3、获取并遍历:ListFiles()(重点)

示例(在某个目录中递归查找文件):

java
public class demo{
    public static void main(String[] args) {
        //完成文件搜索
        File dir = new File("D:/");
        searchFile(dir, "QQ.exe");
    }

    /**
     * 递归搜索文件
     * @param dir 搜索的目录
     * @param fileName 搜索的文件名
     */
    public static void searchFile(File dir, String fileName) {
        if (dir == null || !dir.exists() || dir.isFile() || !dir.canRead()) {
            return; //不搜索
        }
        File[] files = dir.listFiles();
    //        System.out.println(Arrays.toString(files));
        if (files != null && files.length > 0) {
            for (File file : files) {
                // 判断当前对象是否为文件
                if (file.isFile()&&file.getName().equals(fileName)) {
                    System.out.println("找到目标文件" + file.getAbsolutePath());
                }
                else{
                    searchFile(file, fileName);
                }
            }
        }
    }
}

3.4 IO流

3.4.1 概述

  1. 定义:IO指对文件进行输入输出操作

  2. 分类:

    • 输入流、输出流:读取数据写出数据
    • 字节流、字符流:任何二进制文件和处理字符。底层传输的始终为二进制数据
  3. 流体系结构:

    IO流体系
    |
    |---------字节流
    |---------------字节输入流
    |---------------------------InputStream(抽象类)
    |---------------------------FileInputStream(实现类)
    |---------------------------BufferedInputStream(实现类)
    |
    |---------------字节输出流
    |---------------------------OutputStream(抽象类)
    |---------------------------FileOutputStream(实现类)
    |---------------------------BufferedOutputStream(实现类)
    |
    |
    |---------字符流
    |---------------字符输入流
    |---------------------------Reader(抽象类)
    |---------------------------FileReader(实现类)
    |---------------------------BufferedReader(实现类)
    |---------------------------InputStreamReader(实现类)
    |
    |---------------字符输出流
    |---------------------------Writer(抽象类)
    |---------------------------FileWriter(实现类)
    |---------------------------BufferedWriter(实现类)

3.4.2 字节流

含义:从文件中读取字节数据

文件拷贝

字节流实现:

java
public static void copyFile(String srcFile, String destFile){
    long start = System.currentTimeMillis();
    // 1、创建一个文件字节输入流和输出流管道与源文件接通
    InputStream fis = null;
    OutputStream fos = null;
    try {
        fis = new FileInputStream(srcFile);
        fos = new FileOutputStream(destFile);
        // 2、读取一个字节数组,写入一个字节数组
        byte[] buf = new byte[1024];
        int len;
        while ((len = fis.read(buf)) != -1) {
            fos.write(buf, 0, len);  //读取多少个字节,就写入多少个字节
        }
        System.out.println("复制成功");
        fos.flush();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        // 3、释放资源
        try {
            if (fos != null) {
                fos.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            if (fis != null) {
                fis.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("time" + (end - start) + "ms");

    }
}

新写法:

java
public static void copyFile02(String srcFile, String destFile){
    long start = System.currentTimeMillis();
    // 1、创建一个文件字节输入流和输出流管道与源文件接通
    try (
            // 这里只能放置资源对象,用完后,最终会自动调用其close方法进行关闭
            InputStream fis = new FileInputStream(srcFile);
            OutputStream fos = new FileOutputStream(destFile);
            ){
        // 2、读取一个字节数组,写入一个字节数组
        byte[] buf = new byte[1024];
        int len;
        while ((len = fis.read(buf)) != -1) {
            fos.write(buf, 0, len);  //读取多少个字节,就写入多少个字节
        }
        // fos.flush();
        System.out.println("复制成功");
    } catch (Exception e) {
        e.printStackTrace();
    }
    long end = System.currentTimeMillis();
    System.out.println("time" + (end - start) + "ms");
}

字节缓冲流写法:

java
public static void copyFile03(String srcFile, String destFile){
    long start = System.currentTimeMillis();
    try (
            InputStream fis = new FileInputStream(srcFile);
            InputStream bis = new BufferedInputStream(fis);
            OutputStream fos = new FileOutputStream(destFile);
            ) {
        byte[] buf = new byte[1024];
        int len;
        while((len = bis.read(buf)) != -1){
            fos.write(buf, 0, len);
        }
        System.out.println("复制成功");
    } catch (Exception e) {
        e.printStackTrace();
    }
    long end = System.currentTimeMillis();
    System.out.println("time" + (end - start) + "ms");
}

推荐使用字节缓冲流,性能更高。

字节缓冲流先使用8K的容量进行缓冲,等满了在导入内存或者硬盘

3.4.3 字符流

含义:从文件中读取字符数据

1、构造方法:

  • 输入流:

    • FileReader(File file)
    • FileReader(String fileName)
  • 输出流:

    • FileWriter(File file)
    • FileWriter(String pathName)

2、成员方法:

  • 输入流:

    • read()
    • read(char[] cbuf)
  • 输出流:

    • write(int/string c)
    • write(char[] cbuf)
    • write(char[] cbuf, int off, int len)
    • flush()

示例:

字符输入流:

java
try (
        Reader fr = new FileReader(""); //路径自定义
        BufferedReader br = new BufferedReader(fr);
) {
        // 使用FilerReader
    //            char[] buf = new char[1024];
    //            int len;
    //            while ((len = fr.read(buf)) > 0) {
    //                System.out.print(new String(buf, 0, len));
    //            }
        // 使用BufferReader
        String s;
        while ((s = br.readLine()) !=null) {
            System.out.println(s);
        }
}catch (Exception e) {
        e.printStackTrace();
}

字符输出流;

java
try (
        Writer wr = new FileWriter("",true);//路径自定义,true时表示追加,没有时表示覆盖
        BufferedWriter bw = new BufferedWriter(wr);
        ) {
    wr.write("Hello World \ndjklasdkljasdkljasdkljas");
    wr.write('d');
    wr.write("\r\n");
    wr.write('\n');
    wr.flush();
    bw.newLine();

}
catch (Exception e) {
    e.printStackTrace();
}

3.4.4 字符集

  1. 定义:是将一个字符集中的字符映射为一个或多个数字的方法
  2. 乱码产生原因:读取数据完整个数据、解码和编码时的字符集方式不统一
  3. Java中编码和解码:
    • GBK编码使用两个字节来存储一个中文字符
    • UTF-8编码使用三个字节来存储一个中文字符

示例:

字符串加密:

java
import java.util.Arrays;
public class charsetDemo {
    public static void main(String[] args) throws Exception {
        String name = "我爱你中国(_的我)";
        // 编码
        byte[] bytes = name.getBytes("GBK");
        System.out.println(bytes.length);
        System.out.println(Arrays.toString(bytes));
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) (bytes[i] + 3);
//            System.out.println(aByte);
        }
        // 解码
        System.out.println(Arrays.toString(bytes));
        String str = new String(bytes, "GBK");
        System.out.println(str);
        int[] a = {1, 2, 3};
        System.out.println(Arrays.toString(a));
        for (int i = 0; i < a.length; i++) {
            a[i] = a[i] + 1;
        }
        for (int i : a) {
            i++;
            System.out.println(i);
        }
        System.out.println(Arrays.toString(a));
    }
}
/*输出:
17
[-50, -46, -80, -82, -60, -29, -42, -48, -71, -6, 40, 95, -75, -60, -50, -46, 41]
[-47, -43, -77, -79, -57, -26, -39, -45, -68, -3, 43, 98, -72, -57, -47, -43, 44]
颜潮擎儆箭+b盖颜,
[1, 2, 3]
3
4
5
[2, 3, 4]
*/
最近更新