1 字符串相关类
1.1 String
1.1.1 String对象简介
- 简介
String类: 代表字符串。 Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。
String是一个final类,代表不可变的字符序列。
字符串是常量,用双引号引起来表示。 它们的值在创建之后不能更改。
String对象的字符内容是存储在一个字符数组value[]中的。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
- 对象的创建
String str = "hello";
//本质上this.value = new char[0];
String s1 = new String();
//this.value = original.value;
String s2 = new String(String original);
//this.value = Arrays.copyOf(value, value.length);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
1.1.2 String对象的内存结构
- 基本结构
- 产生String不同方式的内存结构
- String的内存结构案例1:
4. String的内存结构案例2:
1.1.3 字符串拼接
字符串拼接的内存结构:
- 常量与常量的拼接结果在常量池。 且常量池中不会存在相同内容的常量。
- 只要其中有一个是变量, 结果就在堆中
- 如果拼接的结果调用intern()方法, 返回值就在常量池中
- String s1 = “a”; 说明:在字符串常量池中创建了一个字面量为"a"的字符串。
- s1 = s1 + “b”; 说明:实际上原来的“a”字符串对象已经丢弃了, 现在在堆空间中产生了一个字符串s1+“b”(也就是"ab")。如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的性能。
- String s2 = “ab”; 说明:直接在字符串常量池中创建一个字面量为"ab"的字符串。
- String s3 = “a” + “b”; 说明: s3指向字符串常量池中已经创建的"ab"的字符串。
- String s4 = s1.intern(); 说明:堆空间的s1对象在调用intern()之后,会将常量池中已经存在的"ab"字符串赋值给s4。
1.1.4 String的常用方法
- int length(): 返回字符串的长度: return value.length
- char charAt(int index): 返回某索引处的字符return value[index]
- boolean isEmpty(): 判断是否是空字符串: return value.length == 0
- String toLowerCase(): 使用默认语言环境, 将 String 中的所有字符转换为小写
- String toUpperCase(): 使用默认语言环境, 将 String 中的所有字符转换为大写
- String trim(): 返回字符串的副本, 忽略前导空白和尾部空白
- boolean equals(Object obj): 比较字符串的内容是否相同
- boolean equalsIgnoreCase(String anotherString): 与equals方法类似, 忽略大小写
- String concat(String str): 将指定字符串连接到此字符串的结尾。 等价于用“+”
- int compareTo(String anotherString): 比较两个字符串的大小
- String substring(int beginIndex): 返回一个新的字符串, 它是此字符串的从beginIndex开始截取到最后的一个子字符串。
- String substring(int beginIndex, int endIndex) : 返回一个新字符串, 它是此字符串从
- beginIndex开始截取到endIndex(不包含)的一个子字符串。
- boolean contains(CharSequence s): 当且仅当此字符串包含指定的 char 值序列时,返回 true
- int indexOf(String str): 返回指定子字符串在此字符串中第一次出现处的索引
- int indexOf(String str, int fromIndex): 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
- int lastIndexOf(String str): 返回指定子字符串在此字符串中最右边出现处的索引
- int lastIndexOf(String str, int fromIndex): 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
注: indexOf和lastIndexOf方法如果未找到都是返回-1 - boolean endsWith(String suffix): 测试此字符串是否以指定的后缀结束
- boolean startsWith(String prefix): 测试此字符串是否以指定的前缀开始
- boolean startsWith(String prefix, int toffset): 测试此字符串从指定索引开始的子字符串是否以指定前缀开始
- String replace(char oldChar, char newChar): 返回一个新的字符串, 它是通过用 newChar替换此字符串中出现的所有 oldChar 得到的。
- String replace(CharSequence target, CharSequence replacement): 使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
- String replaceAll(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
- String replaceFirst(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
- boolean matches(String regex): 告知此字符串是否匹配给定的正则表达式。
- String[] split(String regex): 根据给定正则表达式的匹配拆分此字符串。
- String[] split(String regex, int limit): 根据匹配给定的正则表达式来拆分此字符串, 最多不超过limit个, 如果超过了, 剩下的全部都放到最后一个元素中。
案例:字符串常见操作
// 定义一个字符串对象
String s = "helloworld";
// int length():获取字符串的长度。
System.out.println("s.length:" + s.length());
System.out.println("----------------------");
// char charAt(int index):获取指定索引位置的字符
System.out.println("charAt:" + s.charAt(7));
System.out.println("----------------------");
// int indexOf(int ch):返回指定字符在此字符串中第一次出现处的索引。
System.out.println("indexOf:" + s.indexOf('l'));
System.out.println("----------------------");
// int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引。
System.out.println("indexOf:" + s.indexOf("owo"));
System.out.println("----------------------");
// int indexOf(int ch,int fromIndex):返回指定字符在此字符串中从指定位置后
第一次出现处的索引。
System.out.println("indexOf:" + s.indexOf('l', 4));
System.out.println("indexOf:" + s.indexOf('k', 4)); // -1
System.out.println("indexOf:" + s.indexOf('l', 40)); // -1
System.out.println("----------------------");
// 自己练习:int indexOf(String str,int
// fromIndex):返回指定字符串在此字符串中从指定位置后第一次出现处的索引。
// String substring(int start):从指定位置开始截取字符串,默认到末尾。包含
start这个索引
System.out.println("substring:" + s.substring(5));
System.out.println("substring:" + s.substring(0));
System.out.println("----------------------");
// String substring(int start,int
// end):从指定位置开始到指定位置结束截取字符串。包括start索引但是不包end索引
System.out.println("substring:" + s.substring(3, 8));
System.out.println("substring:" + s.substring(0, s.length()));
1.2 StringBuffer和StringBuilder
- 简介:
当append和insert时,如果原来value数组长度不够,可扩容。
如上这些方法支持方法链操作。
方法链的原理:
- 常用方法
StringBuffer append(xxx):提供了很多的append()方法, 用于进行字符串拼接
StringBuffer delete(int start,int end):删除指定位置的内容
StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
StringBuffer insert(int offset, xxx):在指定位置插入xxx
StringBuffer reverse() :把当前字符序列逆转 public int indexOf(String str)
public String substring(int start,int end)
public int length()
public char charAt(int n )
public void setCharAt(int n ,char ch) - StringBuffer和StringBuilder类
StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列, 而且提供相关功能的方法也一样
面试题:对比String、 StringBuffer、 StringBuilder
String(JDK1.0): 不可变字符序列
StringBuffer(JDK1.0): 可变字符序列、效率低、线程安全
StringBuilder(JDK 5.0):可变字符序列、效率高、 线程不安全
注意:作为参数传递的话,方法内部String不会改变其值, StringBuffer和StringBuilder会改变其值。
- 三者性能对比:
long startTime = 0l;
// long 初始设置 startTime = 0L; 三者的效率测试
long endTime = 0L;
String text = "";
StringBuffer buffer = new StringBuffer("");
StringBuilder builder = new StringBuilder("");
//开始对比
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
buffer.append(String.valueOf(i));
} e
ndTime = System.currentTimeMillis();
System.out.println("StringBuffer的执行时间: " + (endTime -
startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
builder.append(String.valueOf(i));
} e
ndTime = System.currentTimeMillis();
System.out.println("StringBuilder的执行时间: " + (endTime -
startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
text = text + i;
} e
ndTime = System.currentTimeMillis();
System.out.println("String的执行时间: " + (endTime - startTime));
2 日期相关类
2.1 JDK8之前的日期类
2.1.1 System类
- System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
2.1.2 Date
表示特定的瞬间,精确到毫秒
- 构造器:
- Date(): 使用无参构造器创建的对象可以获取本地当前时间。
- Date(long date)
- 常用方法
- getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
- toString():把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue,Wed, Thu, Fri, Sat), zzz是时间标准。
- 其它很多方法都过时了。
案例:
import java.util.Date;
Date date = new Date();
System.out.println(date);
System.out.println(System.currentTimeMillis());
System.out.println(date.getTime());
Date date1 = new Date(date.getTime());
System.out.println(date1.getTime());
System.out.println(date1.toString())
2.1.3 SimpleDateFormat
- Date类的API不易于国际化,大部分被废java.text.SimpleDateFormat类是一个不与语言环境有关的方式来格式化和解析日期的具体类。
- 它允许进行格式化:日期 -> 文本、 解析:文本 -> 日期
- 格式化:
- SimpleDateFormat() :默认的模式和语言环境创建对象
- public SimpleDateFormat(String pattern): 该构造方法可以用参数pattern指定的格式创建一个对象
- public String format(Date date): 方法格式化时间对象date
- 解析:
- public Date parse(String source): 从给定字符串的开始解析文本,以生成一个日期。
案例:
Date date = new Date(); // 产生一个Date实例
// 产生一个formater格式化的实例
SimpleDateFormat formater = new SimpleDateFormat();
System.out.println(formater.format(date));// 打印输出默认的格式
SimpleDateFormat formater2 = new SimpleDateFormat("yyyy年MM月dd日 EEE
HH:mm:ss");
System.out.println(formater2.format(date));
try {
// 实例化一个指定的格式对象
Date date2 = formater2.parse("2008年08月08日 星期一 08:08:08");
// 将指定的日期解析后格式化按指定的格式输出
System.out.println(date2.toString());
} catch (ParseException e) {
e.printStackTrace();
}
2.1.4 Calendar
-
Calendar是一个抽象基类,主用用于完成日期字段之间相互操作的功能。
-
获取Calendar实例的方法
- 使用Calendar.getInstance()方法
- 调用它的子类GregorianCalendar的构造器。
-
一个Calendar的实例是系统时间的抽象表示,通过get(int field)方法来取得想要的时间信息。比如YEAR、 MONTH、 DAY_OF_WEEK、 HOUR_OF_DAY 、MINUTE、 SECOND
- public void set(int field,int value)
- public void add(int field,int amount)
- public final Date getTime()
- public final void setTime(Date date)
-
注意:
-
获取月份时: 一月是0,二月是1,以此类推, 12月是11
-
获取星期时: 周日是1,周二是2 , 。 。。。周六是7
案例:
Calendar calendar = Calendar.getInstance();
// 从一个 Calendar 对象中获取 Date 对象
Date date = calendar.getTime();
// 使用给定的 Date 设置此 Calendar 的时间
date = new Date(234234235235L);
calendar.setTime(date);
calendar.set(Calendar.DAY_OF_MONTH, 8);
System.out.println("当前时间日设置为8后,时间是:" + calendar.getTime());
calendar.add(Calendar.HOUR, 2);
System.out.println("当前时间加2小时后,时间是:" + calendar.getTime());
calendar.add(Calendar.MONTH, -2);
System.out.println("当前日期减2个月后,时间是:" + calendar.getTime());
2.2 JDK8新日期API
Java 8中引入的java.time API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。
Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。新的 java.time 中包含了所有关于本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 方法,用于把 Date 转换成新的表示形式。这些新增的本地化时间日期 API 大大简化了日期时间和本地化的管理。
- java.time – 包含值对象的基础包
- java.time.chrono – 提供对不同的日历系统的访问
- java.time.format – 格式化和解析时间和日期
- java.time.temporal – 包括底层框架和扩展特性
- java.time.zone – 包含时区支持的类
2.2.1 LocalDate、 LocalTime、 LocalDateTime
LocalDate、 LocalTime、 LocalDateTime 类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。
- LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。
- LocalTime表示一个时间,而不是日期。
- LocalDateTime是用来表示日期和时间的, 这是一个最常用的类之一。
注: ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法,也就是公历。
案例:
/*
LocalDate、LocalTime、LocalDateTime 的使用
说明:
1.LocalDateTime相较于LocalDate、LocalTime,使用频率要高
2.类似于Calendar
*/
@Test
public void test1(){
//now():获取当前的日期、时间、日期+时间
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("localDate = " + localDate);
System.out.println("localDateTime = " + localTime);
System.out.println("localDateTime = " + localDateTime);
//of():设置指定的年、月、日、时、分、秒。没有偏移量
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23,
43);
System.out.println("of(2020, 10, 6, 13, 23, 43) = " +
localDateTime1);
//getXxx():获取相关的属性
System.out.println("getDayOfMonth = " +
localDateTime.getDayOfMonth());
System.out.println("getDayOfWeek = " +
localDateTime.getDayOfWeek());
System.out.println("getMonth = " + localDateTime.getMonth());
System.out.println("getMonthValue = " +
localDateTime.getMonthValue());
System.out.println("getMinute = " + localDateTime.getMinute());
//体现不可变性
//withXxx():设置相关的属性
LocalDate localDate1 = localDate.withDayOfMonth(22);
System.out.println("currentDate = " + localDate);
System.out.println("withDayOfMonth(22)" + localDate1);
LocalDateTime localDateTime2 = localDateTime.withHour(4);
System.out.println("currentTime = " + localDateTime);
System.out.println("withHour(4) = " + localDateTime2);
//不可变性
LocalDateTime localDateTime3 = localDateTime.plusMonths(3);
System.out.println("currentTime = " + localDateTime);
System.out.println("plusMonths(3) = " + localDateTime3);
LocalDateTime localDateTime4 = localDateTime.minusDays(6);
System.out.println("currentTime = " + localDateTime);
System.out.println("minusDays(6) = " + localDateTime4);
}
2.2.2 Instant
- Instant:时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳。
- 在处理时间和日期的时候,我们通常会想到年,月,日,时,分,秒。然而,这只是时间的一个模型,是面向人类的。第二种通用模型是面向机器的,或者说是连续的。在此模型中,时间线中的一个点表示为一个很大的数,这有利于计算机处理。 在UNIX中,这个数从1970年开始,以秒为的单位;同样的,在Java中,也是从1970年开始,但以毫秒为单位。
- java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间单位。 Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲, 它只是简单的表示自1970年1月1日0时0分0秒( UTC)开始的秒数。 因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳秒级。
- (1 ns = 10-9 s) 1秒 = 1000毫秒 =106微秒=109纳秒
注意:时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数
案例:
/*
Instant的使用
类似于 java.util.Date类
*/
@Test
public void test2(){
//now():获取本初子午线对应的标准时间
Instant instant = Instant.now();
System.out.println("instant = " + instant);//2019-02-
18T07:29:41.719Z
//添加时间的偏移量
OffsetDateTime offsetDateTime =
instant.atOffset(ZoneOffset.ofHours(8));
System.out.println("atOffset(ZoneOffset.ofHours(8)) = " +
offsetDateTime);//2019-02-18T15:32:50.611+08:00
//toEpochMilli():获取自1970年1月1日0时0分0秒(UTC)开始的毫秒数 ---> Date
类的getTime()
long milli = instant.toEpochMilli();
System.out.println("toEpochMilli = " + milli);
//ofEpochMilli():通过给定的毫秒数,获取Instant实例 -->Date(long millis)
Instant instant1 = Instant.ofEpochMilli(1000L);
System.out.println("ofEpochMilli(1000L) = " + instant1);
}
2.2.3 格式化API
java.time.format.DateTimeFormatter 类:该类提供了三种格式化方法:
预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
本地化相关的格式。如: ofLocalizedDateTime(FormatStyle.LONG)
自定义的格式。如: ofPattern(“yyyy-MM-dd hh:mm:ss”)
案例:
/*
DateTimeFormatter:格式化或解析日期、时间
类似于SimpleDateFormat
*/
@Test
public void test3(){
// 方式一:预定义的标准格式。如:
ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//格式化:日期-->字符串
LocalDateTime localDateTime = LocalDateTime.now();
String str1 = formatter.format(localDateTime);
System.out.println("LocalDateTime = " + localDateTime);
System.out.println("format = " + str1);//2019-02-18T15:42:18.797
//解析:字符串 -->日期
TemporalAccessor parse = formatter.parse("2019-02-18T15:42:18.797");
System.out.println("parse(\"2019-02-18T15:42:18.797\") = " + parse);
// 方式二:
// 本地化相关的格式。如:ofLocalizedDateTime()
// FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT :适用于
LocalDateTime
DateTimeFormatter formatter1 =
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
//格式化
String str2 = formatter1.format(localDateTime);
System.out.println("FormatStyle.LONG = " + str2);//2019年2月18日 下午
03时47分16秒
// 本地化相关的格式。如:ofLocalizedDate()
// FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM /
FormatStyle.SHORT : 适用于LocalDate
DateTimeFormatter formatter2 =
DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
//格式化
String str3 = formatter2.format(LocalDate.now());
System.out.println("FormatStyle.MEDIUM = " + str3);//2019-2-18
// 重点: 方式三:自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MMdd hh:mm:ss");
//格式化
String str4 = formatter3.format(LocalDateTime.now());
System.out.println("ofPattern(\"yyyy-MM-dd hh:mm:ss\")" +
str4);//2019-02-18 03:52:09
}
2.2.3 其他API
ZoneId: 该类中包含了所有的时区信息, 一个时区的ID, 如Europe/Paris
ZonedDateTime: 一个在ISO-8601日历系统时区的日期时间, 如 2007-12-03T10:15:30+01:00 Europe/Paris。
- 其中每个时区都对应着ID, 地区ID都为“ {区域}/{城市}” 的格式, 例如:Asia/Shanghai等
Clock: 使用时区提供对当前即时、 日期和时间的访问的时钟。
持续时间: Duration, 用于计算两个“时间” 间隔
日期间隔: Period, 用于计算两个“日期” 间隔
TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下一个工作日”等操作。
TemporalAdjusters : 该类通过静态方(firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用TemporalAdjuster 的实现。
2.2.4 与传统日期类转换
3 System类
-
System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
-
由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的, 所以也可以很方便的进行调用。
-
成员变量
- System类内部包含in、 out和err三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
-
成员方法
- native long currentTimeMillis():该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
- void exit(int status):该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表异常退出。 使用该方法可以在图形界面编程中实现程序的退出功能等。
- void gc():该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
- String getProperty(String key):该方法的作用是获得系统中属性名为key的属性对应的值。
系统中常见的属性名以及属性的作用如下表所示:
4 Math类
java.lang.Math提供了一系列静态方法用于科学计算。其方法的参数和返回值类型一般为double型。
案例:
public class MathDemo {
public static void main(String[] args) {
// public static final double PI
System.out.println("PI:" + Math.PI);
// public static final double E
System.out.println("E:" + Math.E);
System.out.println("--------------");
// public static int abs(int a):绝对值
System.out.println("abs:" + Math.abs(10));
System.out.println("abs:" + Math.abs(-10));
System.out.println("--------------");
// public static double ceil(double a):向上取整
System.out.println("ceil:" + Math.ceil(12.34));
System.out.println("ceil:" + Math.ceil(12.56));
System.out.println("--------------");
// public static double floor(double a):向下取整
System.out.println("floor:" + Math.floor(12.34));
System.out.println("floor:" + Math.floor(12.56));
System.out.println("--------------");
// public static int max(int a,int b):最大值
System.out.println("max:" + Math.max(12, 23));
// 需求:我要获取三个数据中的最大值
// 方法的嵌套调用
System.out.println("max:" + Math.max(Math.max(12, 23), 18));
// 需求:我要获取四个数据中的最大值
System.out.println("max:"
+ Math.max(Math.max(12, 78), Math.max(34, 56)));
System.out.println("--------------");
// public static double pow(double a,double b):a的b次幂
System.out.println("pow:" + Math.pow(2, 3));
System.out.println("--------------");
// public static double random():随机数 [0.0,1.0)
System.out.println("random:" + Math.random());
// 获取一个1-100之间的随机数
System.out.println("random:" + ((int) (Math.random() * 100) + 1));
System.out.println("--------------");
// public static int round(float a) 四舍五入(参数为double的自学)
System.out.println("round:" + Math.round(12.34f));
System.out.println("round:" + Math.round(12.56f));
System.out.println("--------------");
//public static double sqrt(double a):正平方根
System.out.println("sqrt:"+Math.sqrt(4));
}
}
5 BigInteger和BigDecimal
5.1 BigInteger
- Integer类作为int的包装类,能存储的最大整型值为231-1, Long类也是有限的,最大为263-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。
- java.math包的BigInteger可以表示不可变的任意精度的整数。 BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供java.lang.Math 的所有相关方法。另外, BigInteger 还提供以下运算:模算术、 GCD 计算、质数测试、素数生成、位操作以及一些其他操作。
- 构造器 BigInteger(String val): 根据字符串构建BigInteger对象
- 常用方法
- public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger。
- BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger
- BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger
- BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger
- BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。整数相除只保留整数部分。
- BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的 BigInteger。
- BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟(this % val) 的两个 BigInteger 的数组。
- BigInteger pow(int exponent) :返回其值为 (thisexponent) 的 BigInteger。
案例
public class BigIntegerDemo {
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
BigInteger i = new BigInteger("2147483648");
System.out.println(i);
//加减乘除
BigInteger i1 = new BigInteger("10");
BigInteger i2 = i1.add(new BigInteger("20"));
System.out.println(i2);
BigInteger i3 = i1.subtract(new BigInteger("5"));
System.out.println(i3);
BigInteger i4 = i1.multiply(new BigInteger("5"));
System.out.println(i4);
BigInteger i5 = i1.divide(new BigInteger("2"));
System.out.println(i5);
}
}
5.2 BigDecimal
- 一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中,要求数字精度比较高,故用到java.math.BigDecimal类。
- BigDecimal类支持不可变的、任意精度的有符号十进制定点数。
- 构造器
- public BigDecimal(double val)
- public BigDecimal(String val)
- 常用方法
- public BigDecimal add(BigDecimal augend)
- public BigDecimal subtract(BigDecimal subtrahend)
- public BigDecimal multiply(BigDecimal multiplicand)
- public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
6 正则表达式
正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。
简单来说,正则表达式就是一个很牛逼的字符串处理工具。
正则在线工具 : https://c.runoob.com/front-end/854/?optionGlobl=global
6.1 String类中的正则表达式
public class StringRegexDemo1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (true) {
System.out.println("请输入qq");
String s1 = in.nextLine();
//匹配s1中是否是6-12位数字
System.out.println(s1.matches("^[0-9]{6,12}$"));
}
}
@Test
public void test1() {
String s = "Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统";
// s = s.replaceAll("[a-zA-Z]{1,}", "hello");
s = s.replaceAll("[a-zA-Z]+", "hello");
s = s.replaceAll("\\d+", "world");
System.out.println(s);
}
@Test
public void test2() {
String s1 = "aaa,bbb,123,456,hello,word";
String[] arrs = s1.split(",");
for (int i = 0; i < arrs.length; i++) {
System.out.println(arrs[i]);
}
}
@Test
public void test3() {
String s2 = "hello12333world4567welcome34to4beijing";
String[] arrs2 = s2.split("\\d+");
for (int i = 0; i < arrs2.length; i++) {
System.out.println(arrs2[i]);
}
}
}
7.1 正则表达式常用类
7.1.1 Pattern类
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
● compile():通过正则得到一个Pattern
● matchers():方便正则表达式只是用一次,进行匹配
● matcher():产生Matcher对象,多次正则匹配推荐使用
7.1.2 Matcher类
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
- 索引方法
索引方法提供了有用的索引值,精确表明输入字符串中在哪能找到匹配:
● public int start()返回以前匹配的初始索引。
● public int start(int group) 返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引
● public int end()返回最后匹配字符之后的偏移量。
● public int end(int group)返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。 - 查找方法:
查找方法用来检查输入字符串并返回一个布尔值,表示是否找到该模式:
● public boolean lookingAt() 尝试将从区域开头开始的输入序列与该模式匹配。
● public boolean find()尝试查找与该模式匹配的输入序列的下一个子序列。
● public boolean find(int start)重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
● public boolean matches()尝试将整个区域与模式匹配。
● group()返回上一个匹配项匹配的输入子序列。
● group(int group)返回上一个匹配操作期间给定组捕获的输入子序列。 - 替换方法
替换方法是替换输入字符串里文本的方法:
● public Matcher appendReplacement(StringBuffer sb, String replacement)实现非终端添加和替换步骤。
● public StringBuffer appendTail(StringBuffer sb)实现终端添加和替换步骤。
● public String replaceAll(String replacement)替换模式与给定替换字符串相匹配的输入序列的每个子序列。
● public String replaceFirst(String replacement) 替换模式与给定替换字符串匹配的输入序列的第一个子序列。
● public static String quoteReplacement(String s)返回指定字符串的字面替换字符串。这个方法返回一个字符串,就像传递给Matcher类的appendReplacement 方法一个字面字符串一样工作。
public class RegexDemo1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
//
Pattern pattern = Pattern.compile("^[0-9]{5,12}$"); //正则的编译对象
while (true) {
System.out.println("请输入qq");
String s1 = in.nextLine();
Matcher matcher = pattern.matcher(s1);
System.out.println(matcher.matches()); //全部匹配
// System.out.println(s1.matches("^[0-9]{5,12}$"));
}
}
@Test
public void test1() {
//正则编译对象,只匹配一次可以使用matches方法
System.out.println(Pattern.matches("^[0-9]{5,12}$", "77546313")); //正则是否全部匹配
System.out.println(Pattern.matches("^[0-9]{5,12}$", "123456")); //正则是否全部匹配
System.out.println(Pattern.matches("^[0-9]{5,12}$", "333333")); //正则是否全部匹配
Pattern pattern = Pattern.compile("^[0-9]{5,12}$");
pattern.matcher("77546313").matches();
pattern.matcher("123456").matches();
pattern.matcher("333333").matches();
}
@Test
public void test2() {
//全部匹配
Pattern pattern = Pattern.compile("\\d{5,12}");
Matcher matcher = pattern.matcher("12345a34343434");
System.out.println(matcher.matches()); //全部匹配
}
@Test
public void test3() {
//全部匹配
Pattern pattern = Pattern.compile("\\d{5,12}");
Matcher matcher = pattern.matcher("12345a34343434abc9878989");
while (matcher.find()) {//查找匹配,如果匹配返回ture
String target = matcher.group();//得到上一次匹配的子序列
System.out.println(target + "-" + matcher.start() + "-" + matcher.end()); //start得到上一个匹配的索引开始
}
}
@Test
public void test4() {
String content =
"Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。\n"
+ "Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统。\n"
+ "本教程通过简单的实例将让大家更好的了解 Java 编程语言。\n"
+ "移动操作系统 Android 大部分的代码采用 Java 编程语言编程。";
Pattern pattern = Pattern.compile("([a-zA-Z]+) | (\\d+)");
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
String target = matcher.group(2); //0:全部的正则捕获组,1:的一个小括号的正则补货组
System.out.println(target);
}
}
@Test
public void test6() {
String content =
"Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。\n"
+ "Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统。\n"
+ "本教程通过简单的实例将让大家更好的了解 Java 编程语言。\n"
+ "移动操作系统 Android 大部分的代码采用 Java 编程语言编程。";
//创建一个Pattern对象
Pattern pattern = Pattern.compile("Java");
//创建一个匹配对象
Matcher matcher = pattern.matcher(content);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
//将Java替换为java后,将最后匹配到之前的子串都添加到sb对象中
matcher.appendReplacement(sb, "java");
System.out.println("sb:" + sb);
System.out.println("---------分割线-----------");
}
//将最后匹配到的子串添加到sb中
matcher.appendTail(sb);
System.out.println("sb: " + sb);
}
}
7.2 正则表达式的语法
7.2.1.正则转义符
元符号-转义号\
\符号说明:在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义字符,否则检测不到结果,甚至会报错。
需要用到转义符的字符有:. * + ( )$ / \ ? [ ] ^ { }
注意:在Java的正则表达式中,两个\代表其他语言中的一个\
7.2.2.正则表达式支持字符
正则表达式所支持的合法字符
正则表达式中的特殊字符
预定义字符
方括号表达式
方括号表达式 说明 表示枚举 例如 [abc]表示 a、b、c 其中任意一个字符; [gz]表示 g、z 其中任意一个字符 表示范围:- 例如 [a-f]表示 a~f 范围内的任意字符; [\u0041-\u0056]表示十六进制字符 \u0041 到 \u0056 范围的字符。范围可以和枚举结合使用,如 [a-cx-z],表示 ac、xz 范围内的任意字符 表示求否:^ 例如 [^abc]表示非 a、b、c 的任意字符; [^a-f]表示不是 a~f 范围内的任意字符 表示“与”运算:&& 例如 [a-z&&[def]]是 a~z 和 [def] 的交集,表示 d、ef[a-z&&^bc]]是 a~z 范围内的所有字符,除 b 和 c 之外[ad-z] [a-z&&[m-p]]是 a~z 范围内的所有字符,除 m~p 范围之外的字符 表示“并”运算 并运算与前面的枚举类似。例如 [a-d[m-p]]表示 [a-dm-p]
补充:
Java正则表达式默认是区分字母大小写的,如要实现不区分大小写
(?i)abc表示abc都不区分大小写
a(?i)bc表示bc不区分大小写
a((?i)b)c表示只有b不区分大小写
Pattern pattern=Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
//当创建Pattern对象时,指定Pattern.CASE_INSENSITIVE,表示匹配不区分字母大小写
细节:Java匹配默认贪婪匹配,即尽可能匹配多的,比如"a{3,4}“,表示匹配aaa或者aaaa,但是优先匹配aaaa,例如原字符串中包括"aaaaaa”,匹配"a{3,4}“时,会找到"aaaa”
7.2.3 捕获组(capture group)
从正则表达式左侧开始,每出现一个左括号"("记做一个分组,分组编号从 1 开始。0 代表整个表达式。常用分组构造形式(pattern)
对于时间字符串:2017-04-25,表达式如下
(\d{4})-((\d{2})-(\d{2}))
有 4 个左括号,所以有 4 个分组:
7.3 正则表达式的常见应用
- 验证字符串是否全是汉字
Pattern pattern=Pattern.compile(“1+$”); - 验证字符串是否是邮编
Pattern pattern=Pattern.compile(“^\d{6}$”); - 验证字符串是否是QQ号码
Pattern pattern=Pattern.compile(“2d{4,9}$”); - 验证字符串是否是手机号码(要求:必须以13,14,15,18开头的11位数)
Pattern pattern=Pattern.compile(“^1[3|4|5|8]\d{9}$”); - 验证字符串是否是url
Pattern pattern=Pattern.compile(“^((http|https)😕/)([\w-]+\.)+[\w-]+(\/[\w-?=&/%.#]*)?$”);