Java Doc API 文档
https://docs.oracle.com/en/java/javase/11/docs/api/index.html
Java Math类的常用方法
Java 中的 +、-、*、/ 和 % 等基本算术运算符不能进行更复杂的数学运算,例如,三角函数、对数运算、指数运算等。于是 Java 提供了 Math 工具类来完成这些复杂的运算。
在 Java 中 Math 类封装了常用的数学运算,提供了基本的数学操作,如指数、对数、平方根和三角函数等。Math 类位于 java.lang 包,它的构造方法是 private 的,因此无法创建 Math 类的对象,并且 Math 类中的所有方法都是类方法,可以直接通过类名来调用它们。
静态常量
Math 类中包含 E 和 PI 两个静态常量,正如它们名字所暗示的,它们的值分别等于 e(自然对数)和 π(圆周率)。
例 1
调用 Math 类的 E 和 PI 两个常量,并将结果输出。代码如下:
System.out.println("E 常量的值:" + Math.E);
System.out.println("PI 常量的值:" + Math.PI);
执行上述代码,输出结果如下:
E 常量的值:2.718281828459045
PI 常量的值:3.141592653589793
求最大值、最小值和绝对值
在程序中常见的就是求最大值、最小值和绝对值问题,如果使用 Math 类提供的方法可以很容易实现。这些方法的说明如表 1 所示。
方法 | 说明 |
---|---|
static int abs(int a) | 返回 a 的绝对值 |
static long abs(long a) | 返回 a 的绝对值 |
static float abs(float a) | 返回 a 的绝对值 |
static double abs(double a) | 返回 a 的绝对值 |
static int max(int x,int y) | 返回 x 和 y 中的最大值 |
static double max(double x,double y) | 返回 x 和 y 中的最大值 |
static long max(long x,long y) | 返回 x 和 y 中的最大值 |
static float max(float x,float y) | 返回 x 和 y 中的最大值 |
static int min(int x,int y) | 返回 x 和 y 中的最小值 |
static long min(long x,long y) | 返回 x 和 y 中的最小值 |
static double min(double x,double y) | 返回 x 和 y 中的最小值 |
static float min(float x,float y) | 返回 x 和 y 中的最小值 |
例 2
求 10 和 20 的较大值、15.6 和 15 的较小值、-12 的绝对值,代码如下:
public class Test02 {
public static void main(String[] args) {
System.out.println("10 和 20 的较大值:" + Math.max(10, 20));
System.out.println("15.6 和 15 的较小值:" + Math.min(15.6, 15));
System.out.println("-12 的绝对值:" + Math.abs(-12));
}
}
该程序的运行结果如下:
10和20的较大值:20
15.6和15的较小值:15.0
-12的绝对值:12
求整运算
Math 类的求整方法有很多,详细说明如表 2 所示。
方法 | 说明 |
---|---|
static double ceil(double a) | 返回大于或等于 a 的最小整数 |
static double floor(double a) | 返回小于或等于 a 的最大整数 |
static double rint(double a) | 返回最接近 a 的整数值,如果有两个同样接近的整数,则结果取偶数 |
static int round(float a) | 将参数加上 1/2 后返回与参数最近的整数 |
static long round(double a) | 将参数加上 1/2 后返回与参数最近的整数,然后强制转换为长整型 |
例 3
下面的实例演示了 Math 类中取整函数方法的应用:
import java.util.Scanner;
public class Test03 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.outprintln("请输入一个数字:");
double num = input.nextDouble();
System.out.println("大于或等于 "+ num +" 的最小整数:" + Math.ceil(num));
System.out.println("小于或等于 "+ num +" 的最大整数:" + Math.floor(num));
System.out.println("将 "+ num +" 加上 0.5 之后最接近的整数:" + Math.round(num));
System.out.println("最接近 "+num+" 的整数:" + Math.rint(num));
}
}
执行结果如下:
请输入一个数字:
99.01
大于或等于 99.01 的最小整数:100.0
小于或等于 99.01 的最大整数:99.0
将 99.01 加上 0.5 之后最接近的整数:100
最接近 99.01 的整数:99.0
三角函数运算
Math 类中包含的三角函数方法及其说明如表 3 所示。
方法 | 说明 |
---|---|
static double sin(double a) | 返回角的三角正弦值,参数以孤度为单位 |
static double cos(double a) | 返回角的三角余弦值,参数以孤度为单位 |
static double asin(double a) | 返回一个值的反正弦值,参数域在 [-1,1],值域在 [-PI/2,PI/2] |
static double acos(double a) | 返回一个值的反余弦值,参数域在 [-1,1],值域在 [0.0,PI] |
static double tan(double a) | 返回角的三角正切值,参数以弧度为单位 |
static double atan(double a) | 返回一个值的反正切值,值域在 [-PI/2,PI/2] |
static double toDegrees(double angrad) | 将用孤度表示的角转换为近似相等的用角度表示的角 |
staticdouble toRadians(double angdeg) | 将用角度表示的角转换为近似相等的用弧度表示的角 |
在表 3 中,每个方法的参数和返回值都是 double 类型,参数以弧度代替角度来实现,其中 1 度等于 π/180 弧度,因此平角就是 π 弧度。
例 4
计算 90 度的正弦值、0 度的余弦值、1 的反正切值、120 度的弧度值,代码如下:
public class Test04 {
public static void main(String[] args) {
System.out.println{"90 度的正弦值:" + Math.sin(Math.PI/2));
System.out.println("0 度的余弦值:" + Math.cos(0));
System.out.println("1 的反正切值:" + Math.atan(l));
System.out.println("120 度的弧度值:" + Math.toRadians(120.0));
}
}
在上述代码中,因为 Math.sin() 中的参数的单位是弧度,而 90 度表示的是角度,因此需要将 90 度转换为弧度,即 Math.PI/180*90,故转换后的弧度为 Math.PI/2,然后调用 Math 类中的 sin() 方法计算其正弦值。
该程序的运行结果如下:
90 度的正弦值:1.0
0 的余弦值:1.0
1 的反正切值:0.7853981633974483
120 度的弧度值:2.0943951023931953
指数运算
指数的运算包括求方根、取对数及其求 n 次方的运算。在 Math 类中定义的指数运算方法及其说明如表 4 所示。
方法 | 说明 |
---|---|
static double exp(double a) | 返回 e 的 a 次幂 |
static double pow(double a,double b) | 返回以 a 为底数,以 b 为指数的幂值 |
static double sqrt(double a) | 返回 a 的平方根 |
static double cbrt(double a) | 返回 a 的立方根 |
static double log(double a) | 返回 a 的自然对数,即 lna 的值 |
static double log10(double a) | 返回以 10 为底 a 的对数 |
例 5
使用 Math 类中的方法实现指数的运算,main() 方法中的代码如下:
public class Test05 {
public static void main(String[] args) {
System.out.println("4 的立方值:" + Math.pow(4, 3));
System.out.println("16 的平方根:" + Math.sqrt(16));
System.out.println("10 为底 2 的对数:" + Math.log1O(2));
}
}
该程序的运行结果如下:
4 的立方值:64.0
16 的平方根:4.0
10 为底 2 的对数:0.3010299956639812
Java生成随机数(random()和Random类)
在 Java 中要生成一个指定范围之内的随机数字有两种方法:一种是调用 Math 类的 random() 方法,一种是使用 Random 类。
方法 | 说明 |
---|---|
boolean nextBoolean() | 生成一个随机的 boolean 值,生成 true 和 false 的值概率相等 |
double nextDouble() | 生成一个随机的 double 值,数值介于 [0,1.0),含 0 而不包含 1.0 |
int nextlnt(int n) | 生成一个随机的 int 值,该值介于 [0,n),包含 0 而不包含 n。如果想生成 指定区间的 int 值,也需要进行一定的数学变换 |
long nextLong() | 返回一个随机长整型数字 |
boolean nextBoolean() | 返回一个随机布尔型值 |
float nextFloat() | 返回一个随机浮点型数字 |
例1
下面编写一个 Java 程序,演示如何使用 Random 类提供的方法来生成随机数。具体代码如下:
import java.util.Random;
public class Test06 {
public static void main(String[] args) {
Random r = new Random();
double d1 = r.nextDouble(); // 生成[0,1.0]区间的小数
int i1 = r.nextInt(10); // 生成[0,10]区间的整数
boolean b1 = r.nextBoolean(); // 生成一个随机布尔型值
}
}
Java Date类、Calendar类
日期、日历
在 Java 中获取当前时间,可以使用 java.util.Date 类和 java.util.Calendar 类完成。其中,Date 类主要封装了系统的日期和时间的信息,Calendar 类则会根据系统的日历来解释 Date 对象。下面详细介绍这两个类的具体使用。
Date 类
Date 类表示系统特定的时间戳,可以精确到毫秒。Date 对象表示时间的默认顺序是星期、月、日、小时、分、秒、年。
1. 构造方法
Date 类构造方法。
- Date():此种形式表示分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒),使用该构造方法创建的对象可以获取本地的当前时间。
使用示例如下:
Date date1 = new Date(); // 调用无参数构造函数
Date 类的无参数构造方法获取的是系统当前的时间,显示的顺序为星期、月、日、小时、分、秒、年。
- 常用方法
Date 类提供了许多与日期和事件相关的方法,其中常见的方法如表 1 所示。
方法 | 描述 |
---|---|
boolean after(Date when) | 判断此日期是否在指定日期之后 |
boolean before(Date when) | 判断此日期是否在指定日期之前 |
int compareTo(Date anotherDate) | 比较两个日期的顺序 |
boolean equals(Object obj) | 比较两个日期的相等性 |
long getTime() | 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来,此 Date 对象表示的毫秒数 |
String toString() | 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy。 其中 dow 是一周中的某一天(Sun、Mon、Tue、Wed、Thu、Fri 及 Sat) |
Calendar 类
Calendar 类是一个抽象类,它为特定瞬间与 YEAR、MONTH、DAY_OF—MONTH、HOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(如获得下星期的日期) 提供了一些方法。
创建 Calendar 对象不能使用 new 关键字,因为 Calendar 类是一个抽象类,但是它提供了一个 getInstance() 方法来获得 Calendar类的对象。getInstance() 方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化。
Calendar c = Calendar.getInstance();
当创建了一个 Calendar 对象后,就可以通过 Calendar 对象中的一些方法来处理日期、时间。Calendar 类的常用方法如表 2 所示。
方法 | 描述 |
---|---|
void add(int field, int amount) | 根据日历的规则,为给定的日历字段 field 添加或减去指定的时间量 amount |
boolean after(Object when) | 判断此 Calendar 表示的时间是否在指定时间 when 之后,并返回判断结果 |
boolean before(Object when) | 判断此 Calendar 表示的时间是否在指定时间 when 之前,并返回判断结果 |
void clear() | 清空 Calendar 中的日期时间值 |
int compareTo(Calendar anotherCalendar) | 比较两个 Calendar 对象表示的时间值(从格林威治时间 1970 年 01 月 01 日 00 时 00 分 00 秒至现在的毫秒偏移量),大则返回 1,小则返回 -1,相等返回 0 |
int get(int field) | 返回指定日历字段的值 |
int getActualMaximum(int field) | 返回指定日历字段可能拥有的最大值 |
int getActualMinimum(int field) | 返回指定日历字段可能拥有的最小值 |
int getFirstDayOfWeek() | 获取一星期的第一天。根据不同的国家地区,返回不同的值 |
static Calendar getInstance() | 使用默认时区和语言坏境获得一个日历 |
static Calendar getInstance(TimeZone zone) | 使用指定时区和默认语言环境获得一个日历 |
static Calendar getInstance(TimeZone zone, Locale aLocale) |
使用指定时区和语言环境获得一个日历 |
Date getTime() | 返回一个表示此 Calendar 时间值(从格林威治时间 1970 年 01 月 01 日 00 时 00 分 00 秒至现在的毫秒偏移量)的 Date 对象 |
long getTimeInMillis() | 返回此 Calendar 的时间值,以毫秒为单位 |
void set(int field, int value) | 为指定的日历字段设置给定值 |
void set(int year, int month, int date) | 设置日历字段 YEAR、MONTH 和 DAY_OF_MONTH 的值 |
void set(int year, int month, int date, int hourOfDay, int minute, int second) |
设置字段 YEAR、MONTH、DAY_OF_MONTH、HOUR、 MINUTE 和 SECOND 的值 |
void setFirstDayOfWeek(int value) | 设置一星期的第一天是哪一天 |
void setTimeInMillis(long millis) | 用给定的 long 值设置此 Calendar 的当前时间值 |
Calendar 对象可以调用 set() 方法将日历翻到任何一个时间,当参数 year 取负数时表示公元前。Calendar 对象调用 get() 方法可以获取有关年、月、日等时间信息,参数 field 的有效值由 Calendar 静态常量指定。
Calendar 类中定义了许多常量,分别表示不同的意义。
- Calendar.YEAR:年份。
- Calendar.MONTH:月份。
- Calendar.DATE:日期。
- Calendar.DAY_OF_MONTH:日期,和上面的字段意义完全相同。
- Calendar.HOUR:12小时制的小时。
- Calendar.HOUR_OF_DAY:24 小时制的小时。
- Calendar.MINUTE:分钟。
- Calendar.SECOND:秒。
- Calendar.DAY_OF_WEEK:星期几。
例如,要获取当前月份可用如下代码:
int month = Calendar.getInstance().get(Calendar.MONTH);
如果整型变量 month 的值是 0,表示当前日历是在 1 月份;如果值是 11,则表示当前日历在 12 月份。
使用 Calendar 类处理日期时间的实例如下:
Calendar calendar = Calendar.getInstance(); // 如果不设置时间,则默认为当前时间
calendar.setTime(new Date()); // 将系统当前时间赋值给 Calendar 对象
System.out.println("现在时刻:" + calendar.getTime()); // 获取当前时间
int year = calendar.get(Calendar.YEAR); // 获取当前年份
System.out.println("现在是" + year + "年");
int month = calendar.get(Calendar.MONTH) + 1; // 获取当前月份(月份从 0 开始,所以加 1)
System.out.print(month + "月");
int day = calendar.get(Calendar.DATE); // 获取日
System.out.print(day + "日");
int week = calendar.get(Calendar.DAY_OF_WEEK) - 1; // 获取今天星期几(以星期日为第一天)
System.out.print("星期" + week);
int hour = calendar.get(Calendar.HOUR_OF_DAY); // 获取当前小时数(24 小时制)
System.out.print(hour + "时");
int minute = calendar.get(Calendar.MINUTE); // 获取当前分钟
System.out.print(minute + "分");
int second = calendar.get(Calendar.SECOND); // 获取当前秒数
System.out.print(second + "秒");
int millisecond = calendar.get(Calendar.MILLISECOND); // 获取毫秒数
System.out.print(millisecond + "毫秒");
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); // 获取今天是本月第几天
System.out.println("今天是本月的第 " + dayOfMonth + " 天");
int dayOfWeekInMonth = calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH); // 获取今天是本月第几周
System.out.println("今天是本月第 " + dayOfWeekInMonth + " 周");
int many = calendar.get(Calendar.DAY_OF_YEAR); // 获取今天是今年第几天
System.out.println("今天是今年第 " + many + " 天");
Calendar c = Calendar.getInstance();
c.set(2012, 8, 8); // 设置年月日,时分秒将默认采用当前值
System.out.println("设置日期为 2012-8-8 后的时间:" + c.getTime()); // 输出时间
上面的示例代码演示了 Calendar 类中的方法与常量的结合使用,从而完成处理日期的操作。
Java日期格式化(DateFormat类和SimpleDateFormat类)
在 Java 中,可以使用 DateFormat 类和 SimpleDateFormat 类来格式化日期,下面详细介绍这两个格式化日期类的使用。
DateFormat 类
DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。日期/时间格式化子类(如 SimpleDateFormat)允许进行格式化(也就是日期→文本)、解析(文本→日期)和标准化日期。
在创建 DateFormat 对象时不能使用 new 关键字,而应该使用 DateFormat 类中的静态方法 getDateInstance(),示例代码如下:
DateFormat df = DateFormat.getDateInstance();
在创建了一个 DateFormat 对象后,可以调用该对象中的方法来对日期/时间进行格式化。
格式化样式主要通过 DateFormat 常量设置。将不同的常量传入方法中,以控制结果的长度。DateFormat 类的常量如下。
- SHORT:完全为数字,如 12.5.10 或 5:30pm。
- MEDIUM:较长,如 May 10,2016。
- LONG:更长,如 May 12,2016 或 11:15:32am。
- FULL:是完全指定,如 Tuesday、May 10、2012 AD 或 11:l5:42am CST。
使用 DateFormat 类格式化曰期/时间的示例如下:
// 获取不同格式化风格和中国环境的日期
DateFormat df1 = DateFormat.getDateInstance(DateFormat.SHORT, Locale.CHINA);
DateFormat df2 = DateFormat.getDateInstance(DateFormat.FULL, Locale.CHINA);
DateFormat df3 = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.CHINA);
DateFormat df4 = DateFormat.getDateInstance(DateFormat.LONG, Locale.CHINA);
// 获取不同格式化风格和中国环境的时间
DateFormat df5 = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.CHINA);
DateFormat df6 = DateFormat.getTimeInstance(DateFormat.FULL, Locale.CHINA);
DateFormat df7 = DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.CHINA);
DateFormat df8 = DateFormat.getTimeInstance(DateFormat.LONG, Locale.CHINA);
// 将不同格式化风格的日期格式化为日期字符串
String date1 = df1.format(new Date());
String date2 = df2.format(new Date());
String date3 = df3.format(new Date());
String date4 = df4.format(new Date());
// 将不同格式化风格的时间格式化为时间字符串
String time1 = df5.format(new Date());
String time2 = df6.format(new Date());
String time3 = df7.format(new Date());
String time4 = df8.format(new Date());
// 输出日期
System.out.println("SHORT:" + date1 + " " + time1);
System.out.println("FULL:" + date2 + " " + time2);
System.out.println("MEDIUM:" + date3 + " " + time3);
System.out.println("LONG:" + date4 + " " + time4);
运行该段代码,输出的结果如下:
SHORT:18-10-15 上午9:30
FULL:2018年10月15日 星期一 上午09时30分43秒 CST
MEDIUM:2018-10-15 9:30:43
LONG:2018年10月15日 上午09时30分43秒
该示例主要介绍了 DateFormat 类中方法与常量的结合使用,通过使用 DateFomat 类可以对日期进行不同风格的格式化。
SimpleDateFormat 类(常用)
如果使用 DateFormat 类格式化日期/时间并不能满足要求,那么就需要使用 DateFormat 类的子类——SimpleDateFormat。
SimpleDateFormat 是一个以与语言环境有关的方式来格式化和解析日期的具体类,它允许进行格式化(日期→文本)、解析(文本→日期)和规范化。SimpleDateFormat 使得可以选择任何用户定义的日期/时间格式的模式。
SimpleDateFormat 类主要有如下 3 种构造方法。
- SimpleDateFormat():用默认的格式和默认的语言环境构造 SimpleDateFormat。
- SimpleDateFormat(String pattern):用指定的格式和默认的语言环境构造 SimpleDateFormat。
- SimpleDateFormat(String pattern,Locale locale):用指定的格式和指定的语言环境构造 SimpleDateFormat。
SimpleDateFormat 自定义格式中常用的字母及含义如表 2 所示。
字母 | 含义 | 示例 |
---|---|---|
y | 年份。一般用 yy 表示两位年份,yyyy 表示 4 位年份 | 使用 yy 表示的年扮,如 11; 使用 yyyy 表示的年份,如 2011 |
M | 月份。一般用 MM 表示月份,如果使用 MMM,则会 根据语言环境显示不同语言的月份 |
使用 MM 表示的月份,如 05; 使用 MMM 表示月份,在 Locale.CHINA 语言环境下,如“十月”;在 Locale.US 语言环境下,如 Oct |
d | 月份中的天数。一般用 dd 表示天数 | 使用 dd 表示的天数,如 10 |
D | 年份中的天数。表示当天是当年的第几天, 用 D 表示 | 使用 D 表示的年份中的天数,如 295 |
E | 星期几。用 E 表示,会根据语言环境的不同, 显示不 同语言的星期几 |
使用 E 表示星期几,在 Locale.CHINA 语 言环境下,如“星期四”;在 Locale.US 语 言环境下,如 Thu |
H | 一天中的小时数(0~23)。一般用 HH 表示小时数 | 使用 HH 表示的小时数,如 18 |
h | 一天中的小时数(1~12)。一般使用 hh 表示小时数 | 使用 hh 表示的小时数,如 10 (注意 10 有 可能是 10 点,也可能是 22 点) |
m | 分钟数。一般使用 mm 表示分钟数 | 使用 mm 表示的分钟数,如 29 |
s | 秒数。一般使用 ss 表示秒数 | 使用 ss 表示的秒数,如 38 |
S | 毫秒数。一般使用 SSS 表示毫秒数 | 使用 SSS 表示的毫秒数,如 156 |
例 1
编写 Java 程序,使用 SimpleDateFormat 类格式化当前日期并打印,日期格式为“xxxx 年 xx 月 xx 日星期 xxx 点 xx 分 xx 秒”,具体的实现代码如下:
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test13 {
public static void main(String[] args) {
Date now = new Date(); // 创建一个Date对象,获取当前时间
// 指定格式化格式
SimpleDateFormat f = new SimpleDateFormat("今天是 " + "yyyy 年 MM 月 dd 日 E HH 点 mm 分 ss 秒");
System.out.println(f.format(now)); // 将当前时间袼式化为指定的格式
//Date d2 = format.parse("2022-03-16 23:44:24");
}
}
该程序的运行结果如下:
今天是 2018 年 10 月 15 日 星期一 09 点 26 分 23 秒
Java数字格式化(DecimalFormat)
DecimalFormat 是 NumberFormat 的一个子类,用于格式化十进制数字。DecimalFormat 类包含一个模式和一组符号,常用符号的说明如表 1 所示。
符号 | 说明 |
---|---|
0 | 显示数字,如果位数不够则补 0 |
# | 显示数字,如果位数不够不发生变化 |
例 1
下面编写一个 Java 程序,演示如何使用 DecimalFormat 类将数字转换成各种格式,实现代码如下。
//.后面的0,不够补0
DecimalFormat format1 = new DecimalFormat("0.000");
//,###:三个一组分割
//.#后面不够不补充,
DecimalFormat format2 = new DecimalFormat(",###.###");
double d = 11232321100.6;
System.out.println(format1.format(d));
System.out.println(format2.format(d));
Java String 类
字符串是 Java 中特殊的类,使用方法像一般的基本数据类型,被广泛应用在 Java 编程中。Java 没有内置的字符串类型,而是在标准 Java 类库中提供了一个 String 类来创建和操作字符串。
在 Java 中定义一个字符串最简单的方法是用双引号把它包围起来。这种用双引号括起来的一串字符实际上都是 String 对象,如字符串“Hello”在编译后即成为 String 对象。因此也可以通过创建 String 类的实例来定义字符串。
不论使用哪种形式创建字符串,字符串对象一旦被创建,其值是不能改变的,但可以使用其他变量重新赋值的方式进行更改。
直接定义字符串
直接定义字符串是指使用双引号表示字符串中的内容,例如“Hello Java”、“Java 编程”等。具体方法是用字符串常量直接初始化一个 String 对象,示例如下:
String str = "Hello Java";
或者
String str;
str = "Hello Java";
注意:字符串变量必须经过初始化才能使用。
例 1
下面的实例演示了直接创建字符串的几种用法。
String str = "我是一只小小鸟"; // 结果:我是一只小小鸟
String word = "I am a bird"; // 结果:I am a bird
word = "Let\'s say that it\'s true"; // 结果:Let's say that it's true
System.out.println(word);
word = "北京\\上海\\广州"; // 结果:北京\上海\广州
使用 String 类定义
前面我们提到在 Java 中每个双引号定义的字符串都是一个 String 类的对象。因此,可以通过使用 String 类的构造方法来创建字符串,该类位于 java.lang 包中。
String 类的构造方法有多种重载形式,每种形式都可以定义字符串。下面介绍最常用的几种形式。
1. String()
初始化一个新创建的 String 对象,表示一个空字符序列。
2. String(String original)
初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列。换句话说,新创建的字符串是该参数字符串的副本。例如:
String str1 = new String("Hello Java");
String str2 = new String(str1);
3. String(char[ ]value)
分配一个新的字符串,将参数中的字符数组元素全部变为字符串。该字符数组的内容已被复制,后续对字符数组的修改不会影响新创建的字符串。例如:
char a[] = {'H','e','l','l','0'};
String sChar = new String(a);
a[1] = 's';
上述 sChar 变量的值是字符串“Hello”。 即使在创建字符串之后,对 a 数组中的第 2 个元素进行了修改,但未影响 sChar 的值。
4. String中常用的方法
length()
字符串的长度
String a = "Hello Word!";
System.out.println(a.length);
//输出的结果是字符串长度10。
charAt()
截取一个字符
String a = "Hello Word";
System.out.println(a.charAt(1));
//输出的结果是字符串a的下标为1的字符e。
getBytes()
将字符串变成一个byte数组
String a = "Hello Word";
byte b[] = a.getBytes();
System.out.println(new String(b));
//输出的结果为Hello Word的byte数组。
toCharArray()
将字符串变成一个字符数组
String a = "Hello Word";
char[]b = a.toCharArray();
System.out.println(b);
//输出的结果为Hello Word字符数组。
equals()和equalsIgnoreCase():常用的
比较两个字符串是否相等,前者区分大小写,后者不区分
String a = "Hello Word";
String b = "hello word";
System.out.println(a.equals(b));
System.out.println(a.equalsIgnoreCase(b));
//输出的结果为第一条为false,第二条为true。
startsWith()和endsWith()
判断字符串是不是以特定的字符开头或结束
String a = "Hello Word";
System.out.println(a.startsWith("ee"));
System.out.println(a.endsWith("rd"));
//输出的结果第一条为false,第二条为true。
toUpperCase()和toLowerCase()
将字符串转换为大写或小写
String a = "Hello Word";
System.out.println(a.toUpperCase());
System.out.println(a.toLowerCase());
输出的结果第一条为“HELLO WORD”,第二条为“hello word”。
trim()
去掉起始和结束的空格
String a = " Hello Word ";
System.out.println(a.trim());
//输出的结果为“Hello Word”。
substring()
截取字符串
String a = "Hello Word";
System.out.println(a.substring(0, 5));
System.out.println(a.substring(6));
//输出的结果第一条为“Hello”,第一个参数0(beginIndex)
//是开始截取的位置,第二个参数5(endIndex)是截取结束的位置
//输出的结果第二条是“Word”,参数6(beginIndex)是开始截取的位置。
indexOf()和lastIndexOf()
前者是查找字符或字符串第一次出现的地方,后者是查找字符或字符串最后一次出现的地方
String a = "Hello Word";
System.out.println(a.indexOf("o"));
System.out.println(a.lastIndexOf("o"));
//输出的结果第一条是4,是o第一次出现的下标,第二条是7,是o最后一次出现的下标。
replace()
替换
String a = "Hello Word";
String b = "你好";
System.out.println(a.replace(a, b));
System.out.println(a.replace(a, "HELLO WORD"));
System.out.println(b.replace("你", "大家"));
//输出的结果第一条为“你好”,第二条为“HELLO WORD”,第三条为“大家好”。
split()
字符串分割
String name = "张三";
System.out.println(name.split("")[0]);//张
System.out.println(name.split("")[1]);//三
String info = "我,热,爱Java编程";
String[] infos = info.split(",");//[我,热,爱Java编程]
for (String s : infos) {
System.out.println(s);
}
Java String:字符串常量池
作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么?
代码:从字符串常量池中获取相应的字符串
String str1 = "hello";//将字符串存储到常量池中
String str2 = "hello";//拿到的是上面的hello
System.out.println("str1 == str2 -> " + (str1 == str2) ); //true
String str3 = new String("hello");//新创建对象,存储在堆中
Systme.out.println(str1 == str3);//false
StringBuffer和StringBuilder
StringBuffer
StringBuffer称为字符串缓冲区,它的工作原理是:预先申请一块内存,存放字符序列,如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。StringBuffer是可变对象,这个是String最大的不同
public class StringBufferTest01 {
public static void main(String[] args) {
StringBuffer sbStr = new StringBuffer();
for (int i=0; i<100; i++) {
//sbStr.append(i);
//sbStr.append(",");
//方法链的编程风格
sbStr.append(i).append(",");
//拼串去除逗号
//sbStr.append(i);
//if (i != 99) {
// sbStr.append(",");
//}
}
//可以输出
System.out.println(sbStr);
System.out.println("");
System.out.println(sbStr.toString());
System.out.println("");
//去除逗号
System.out.println(sbStr.toString().substring(0,sbStr.toString().length()-1));
System.out.println("");
System.out.println(sbStr.substring(0, sbStr.length()-1));
}
}
StringBuilder
用法同StringBuffer,StringBuilder和StringBuffer的区别是StringBuffer中所有的方法都是同步的,是线程安全的,但速度慢,StringBuilder的速度快,但不是线程安全的
String、StringBuilder、StringBuffer对比
1.可变与不可变
String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知道string对象是不可变的。
private final char value[];
StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,如下就是,可知这两种对象都是可变的。
char[] value;
2.是否多线程安全
String中的对象是不可变的,也就可以理解为常量,显然线程安全。
AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的
StringBuilder与StringBuffer共同点
StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)。
抽象类与接口的其中一个区别是:抽象类中可以定义一些子类的公共方法,子类只需要增加新的功能,不需要重复写已经存在的方法;而接口中只是对方法的申明和常量的定义。
StringBuilder、StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(…)。只是StringBuffer会在方法上加synchronized关键字,进行同步。
最后,如果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。
正则表达式
一、String字符串匹配
//public boolean matches(String regex):判断是否与正则表达式匹配,匹配返回true
// 只能是 a b c
System.out.println("a".matches("[abc]")); // true
System.out.println("z".matches("[abc]")); // false
// 不能出现a b c
System.out.println("a".matches("[^abc]")); // false
System.out.println("z".matches("[^abc]")); // true
System.out.println("a".matches("\\d")); // false
System.out.println("3".matches("\\d")); // true
System.out.println("333".matches("\\d")); // false
System.out.println("z".matches("\\w")); // true
System.out.println("2".matches("\\w")); // true
System.out.println("21".matches("\\w")); // false
System.out.println("你".matches("\\w")); //false
System.out.println("你".matches("\\W")); // true
System.out.println("---------------------------------");
//以上正则匹配只能校验单个字符。
// 校验密码
// 必须是数字 字母 下划线 至少 6位
System.out.println("2442fsfsf".matches("\\w{6,}"));
System.out.println("244f".matches("\\w{6,}"));
// 验证码 必须是数字和字符 必须是4位
System.out.println("23dF".matches("[a-zA-Z0-9]{4}"));
System.out.println("23_F".matches("[a-zA-Z0-9]{4}"));
System.out.println("23dF".matches("[\\w&&[^_]]{4}"));
System.out.println("23_F".matches("[\\w&&[^_]]{4}"));
System.out.print("请输入密码:");
Scanner scanner = new Scanner(System.in);
String password = scanner.next();
if(password.matches("\\w{2,10}")){
System.err.println("密码符合规范");
}else{
System.err.println("密码不符合规范");
}
二、String的replace、split
正则表达式在方法中的应用。
public String[] split(String regex):
— 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。
public String replaceAll(String regex,String newStr)
— 按照正则表达式匹配的内容进行替换
String names = "小路dhdfhdf342蓉儿43fdffdfbjdfaf小何";
String[] arrs = names.split("\\w+");
for (int i = 0; i < arrs.length; i++) {
System.out.println(arrs[i]);
}
String names2 = names.replaceAll("\\w+", " ");
System.out.println(names2);
//将数字都给删除
String str = "fdsfds3432432fdsfds564654dfsgfd564654";
str = str.replaceAll("\\d+","");
System.out.println(str);
三、匹配提取
java.util.regex 包主要包括以下三个类:
- Pattern 类:pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
- Matcher 类:Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
- PatternSyntaxException:PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
以下实例中使用了正则表达式 .abc. 用于查找字符串中是否包了 abc 子串:
public static void main(String[] args){
String content = "I am abc from abcdef.com.";
String pattern = ".*abcdef.*";
boolean isMatch = Pattern.matches(pattern, content);
System.out.println("字符串中是否包含了 'abcdef' 子字符串? " + isMatch);
}
String rs = "你好,我的邮箱是12sdfds3456@qq.com,fdsfa@432fds.mm手机号是17312341234";
// 需求:从上面的内容中爬取出 电话号码和邮箱。
// 1、定义爬取规则,字符串形式
String regex = "(\\w{0,20}@\\w{0,6}\\.\\w{2,6})|(\\d{11})";
// 2、把这个爬取规则编译成匹配对象。
Pattern pattern = Pattern.compile(regex);
// 3、得到一个内容匹配器对象
Matcher matcher = pattern.matcher(rs);
// 4、开始找了
while (matcher.find()) {
String rs1 = matcher.group();
System.out.println(rs1);
}
四、匹配规则
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Pattern.html
字符类
[abc] a, b, 或c(简单类)
[^abc] a除, b, 或c(否定)以外的任何字符
[a-zA-Z] a通过z 或A通过Z,包括(范围)
[a-d[m-p]] a通过d,或m通过p:([a-dm-p]联合)
[a-z&&[def]] d, e, or f(intersection)
[a-z&&[^bc]] a通过z,除了b和c:([ad-z]减法)
[a-z&&[^m-p]] a通过z,而不是m通过p:([a-lq-z]减法
预定义的字符类
. 任何字符(可能与行终止符匹配,也可能不匹配)
\d 一个数字:[0-9]
\D 非数字:[^0-9]
\h 水平空白字符: [ \t\xA0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000]
\H 非水平空白字符:[^\h]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\v 垂直空白字符:[\n\x0B\f\r\x85\u2028\u2029]
\V 非垂直空白字符:[^\v]
\w 一个字字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
字符 | 说明 |
---|---|
\ | 将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如, n匹配字符 n。\n 匹配换行符。序列 \\\\ 匹配 \\ ,\\( 匹配 (。 |
^ | 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与”\n”或”\r”之后的位置匹配。 |
$ | 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与”\n”或”\r”之前的位置匹配。 |
* | 零次或多次匹配前面的字符或子表达式。例如,zo 匹配”z”和”zoo”。 等效于 {0,}。 |
+ | 一次或多次匹配前面的字符或子表达式。例如,”zo+”与”zo”和”zoo”匹配,但与”z”不匹配。+ 等效于 {1,}。 |
? | 零次或一次匹配前面的字符或子表达式。例如,”do(es)?”匹配”do”或”does”中的”do”。? 等效于 {0,1}。 |
{n} | n 是非负整数。正好匹配 n 次。例如,”o{2}”与”Bob”中的”o”不匹配,但与”food”中的两个”o”匹配。 |
{n,} | n 是非负整数。至少匹配 n 次。例如,”o{2,}”不匹配”Bob”中的”o”,而匹配”foooood”中的所有 o。”o{1,}”等效于”o+”。”o{0,}”等效于”o*”。 |
{n,m} | m 和 n 是非负整数,其中 n <= m。匹配至少 n 次,至多 m 次。例如,”o{1,3}”匹配”fooooood”中的头三个 o。’o{0,1}’ 等效于 ‘o?’。注意:您不能将空格插入逗号和数字之间。 |
? | 当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是”非贪心的”。”非贪心的”模式匹配搜索到的、尽可能短的字符串,而默认的”贪心的”模式匹配搜索到的、尽可能长的字符串。例如,在字符串”oooo”中,”o+?”只匹配单个”o”,而”o+”匹配所有”o”。 |
. | 匹配除”\r\n”之外的任何单个字符。若要匹配包括”\r\n”在内的任意字符,请使用诸如”[\s\S]”之类的模式。 |
(pattern) | 匹配 pattern 并捕获该匹配的子表达式。可以使用 $0…$9 属性从结果”匹配”集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用”\(“或者”\)”。 |
(?:pattern) | 匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用”or”字符 (|) 组合模式部件的情况很有用。例如,’industr(?:y|ies) 是比 ‘industry|industries’ 更经济的表达式。 |
(?=pattern) | 执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,’Windows (?=95|98|NT|2000)’ 匹配”Windows 2000”中的”Windows”,但不匹配”Windows 3.1”中的”Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。 |
(?!pattern) | 执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,’Windows (?!95|98|NT|2000)’ 匹配”Windows 3.1”中的 “Windows”,但不匹配”Windows 2000”中的”Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。 |
x|y | 匹配 x 或 y。例如,’z|food’ 匹配”z”或”food”。’(z|f)ood’ 匹配”zood”或”food”。 |
x&y | 匹配 x 并且 y。”ab”.matches(“[a&b]+”)->true |
[xyz] | 字符集。匹配包含的任一字符。例如,”[abc]”匹配”plain”中的”a”。 |
[^xyz] | 反向字符集。匹配未包含的任何字符。例如,”[^abc]”匹配”plain”中”p”,”l”,”i”,”n”。 |
[a-z] | 字符范围。匹配指定范围内的任何字符。例如,”[a-z]”匹配”a”到”z”范围内的任何小写字母。 |
[^a-z] | 反向范围字符。匹配不在指定的范围内的任何字符。例如,”[^a-z]”匹配任何不在”a”到”z”范围内的任何字符。 |
\b | 匹配一个字边界,即字与空格间的位置。例如,”er\b”匹配”never”中的”er”,但不匹配”verb”中的”er”。 |
\B | 非字边界匹配。”er\B”匹配”verb”中的”er”,但不匹配”never”中的”er”。 |
\cx | 匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在 A-Z 或 a-z 之间。如果不是这样,则假定 c 就是”c”字符本身。 |
\d | 数字字符匹配。等效于 [0-9]。 |
\D | 非数字字符匹配。等效于 [^0-9]。 |
\f | 换页符匹配。等效于 \x0c 和 \cL。 |
\n | 换行符匹配。等效于 \x0a 和 \cJ。 |
\r | 匹配一个回车符。等效于 \x0d 和 \cM。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。 |
\S | 匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。 |
\t | 制表符匹配。与 \x09 和 \cI 等效。 |
\v | 垂直制表符匹配。与 \x0b 和 \cK 等效。 |
\w | 匹配任何字类字符,包括下划线。与”[A-Za-z0-9_]”等效。 |
\W | 与任何非单词字符匹配。与”[^A-Za-z0-9_]”等效。 |
\xn | 匹配 n,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,”\x41”匹配”A”。”\x041”与”\x04”&”1”等效。允许在正则表达式中使用 ASCII 代码。 |
\num | 匹配 num,此处的 num 是一个正整数。到捕获匹配的反向引用。例如,”(.)\1”匹配两个连续的相同字符。 |
\n | 标识一个八进制转义码或反向引用。如果 \n 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。 |
\nm | 标识一个八进制转义码或反向引用。如果 \nm 前面至少有 nm 个捕获子表达式,那么 nm 是反向引用。如果 \nm 前面至少有 n 个捕获,则 n 是反向引用,后面跟有字符 m。如果两种前面的情况都不存在,则 \nm 匹配八进制值 nm,其中 n 和 m 是八进制数字 (0-7)。 |
\nml | 当 n 是八进制数 (0-3),m 和 l 是八进制数 (0-7) 时,匹配八进制转义码 nml。 |
\un | 匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (©)。 |