目录
java.lang.StringBuffer、java.lang.StringBuilder
java.util.concurrent.ThreadLocalRandom
java.util.Date,java.text.SimpleDateFormat
六、正则表达式 Regular Expression,regex
零、java.lang.Object
一、字符串
java.lang.String
- 声明String类变量
String str1 = "hello"; // 直接赋值方式创建对象是在方法区的常量池
char[] cstr = {'w','o','r','l','d'};
String str2 = new String(cstr); // 通过构造方法创建字符串对象是在堆内存
- 构造器
String(byte[] bytes)
String(byte[] bytes, Charset charset)
String(byte[] bytes, String charsetName)
String(byte[] bytes, int offset, int length)
String(byte[] bytes, int offset, int length, Charset charset)
String(byte[] bytes, int offset, int length, String charsetName)
String(char[] value)
String(char[] value, int index, int count)
String(String original)
String(StringBuffer buffer)
String(StringBuilder builder)
- 字符串拼接
" ".concat(str2); //常量字符串也可以使用concat方法
String str3 = str1.concat(str2);
String str4 = str1 + str2; //对于字符串的加运算,当编译成class文件时,会自动编译为StringBuffer来进行字符串的连接操作
//相当于String str4 = new StringBuffer().append(str1).append(str2).toString();
- String 类是不可改变的,所以你一旦创建了 String 对象,那它的值就无法改变了。因为字符串实际上内部封装了一个 char 数组,并且char数组是被final修饰的。
// 表面上s被改变了,实际上s只是一个指向内存中存放“hello”字符串的引用,当s指向另一个字符串“world”时,“hello”还留在内存中
String s = "hello";
System.out.println(s); //输出hello
s = "world";
System.out.println(s); //输出world
- 字符串直接量与常量池:当程序第一次使用某个字符串直接量时,Java会使用常量池来缓存该字符串直接量,如果程序后面需要用到该直接量,Java不会再占用内存创建新的字符串,而是直接引用常量池中的字符串直接量。使用new String("staff")创建字符串时,JVM会先使用常量池来管理"str"直接量,再调用String类的构造器来创建一个新的String对象,新创建的String对象被保存在堆内存中
String s1 = "saff";
String s2 = "saff";
String s3 = new String("saff");
String s4 = new String("saff");
System.out.println(s1.equals(s2)); // true
System.out.println(s1.equals(s3)); // true
System.out.println(s1==s2); // true
System.out.println(s1==s3); // false
// 下面两次输出的hashCode相同
System.out.println(s3.hashCode());
System.out.println(s4.hashCode());
String s1 = "a" + "b" + "c";
String s2 = "abc";
String s3 = "ab";
String s4 = "c";
String s5 = s3 + s4; // 表达式右边只要有字符串变量,编译时就无法确定,不会执行宏替换
System.out.println(s1 == s2); // true
System.out.println(s1.equals(s2)); // true
System.out.println(s1 == s5); // false;
System.out.println(s1.equals(s5)); // true
- 实例方法
int len = str.length();
String str = "hello";
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
System.out.println(c);
}
String newUTF8Str = new String(oldGBKStr.getBytes("GBK"), "UTF-8");
java.lang.StringBuffer、java.lang.StringBuilder
- String:字符串常量是immutable(不可变)的。因为内部用于存放字符的数组被声明为final的,只能赋值一次,不可再更改
- StringBuffer:字符串变量(线程安全)若要频繁对字符串内容进行修改,出于效率考虑最好使用StringBuffer
- StringBuilder:字符串变量(非线程安全)在内部 StringBuilder 对象被当作是一个包含字符序列的变长数组
- 基本原则:操作少量的数据用 String ;单线程操作大量数据用StringBuilder ;多线程操作大量数据用StringBuffer
- StringBuilder构造方法
StringBuilder()
StringBuilder(int capacity)
StringBuilder(CharSequence seq)
StringBuilder(String str)
- 常用方法
int capacity() 返回当前容量 (理论值)
int length() 返回长度(已经存储的字符个数)
StringBuilder append(Object obj) 添加数据,并返回自身对象
StringBuilder reverse() 反转字符串
StringBuilder->String
toString()
String->StringBuilder
StringBuilder()
二、java.lang.System
- 静态常量
static InputStream in
static PrintStream out
static PrintStream err
- 静态方法
// 时间戳:以1970年1月1日为起点,在UNIX中以秒为单位,在Java中以毫秒为单位
static long currentTimeMillis() // 当前时间戳,毫秒
static long nanoTime() // 当前时间戳,纳秒
static void exit(int status)
static void gc()
static System.Logger getLogger(String name)
static String lineSeparator()
- 计算程序运行时间
// 测量时间间隔
try {
long start = System.currentTimeMillis();
Thread.sleep(3000);
long end = System.currentTimeMillis();
long diff = end - start;
System.out.println(diff);
} catch (Exception e) {
e.printStackTrace();
}
三、数学运算
java.lang.Math
Math.random(); // 返回[0,1.0)之间的浮点数
java.util.Random
Random方法:
void setSeed(long seed)
Random random = new Random();
protected int next(int bits)
boolean nextBoolean()
void nextBytes(byte[] bytes)
double nextDouble()
float nextFloat()
double nextGaussian()
int nextInt()
int nextInt(int bound)
long nextLong()
java.util.concurrent.ThreadLocalRandom
import java.util.Random;
public class RandomDemo {
public static void main(String[] args) {
// 默认当前时间毫秒值作为种子,System.currentTimeMillis()
Random random = new Random();
System.out.println(random.nextBoolean());
System.out.println(random.nextInt());
System.out.println(random.nextInt(100)); // [0,100)
System.out.println(random.nextFloat());
System.out.println(random.nextDouble());
System.out.println(random.nextLong());
System.out.println(random.nextGaussian()); // 生成均值为0.0,方差为1.0的伪高斯数
}
}
ThreadLocalRandom方法:
static ThreadLocalRandom current()
void setSeed(long seed)
protected int next(int bits)
boolean nextBoolean()
double nextDouble()
double nextDouble(double bound)
double nextDouble(double origin, double bound)
float nextFloat()
int nextInt()
int nextInt(int bound)
int nextInt(int origin, int bound)
long nextLong()
long nextLong(long bound)
long nextLong(long origin, long bound)
import java.util.concurrent.ThreadLocalRandom;
public class Demo {
public static void main(String[] args) {
ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
System.out.println(threadLocalRandom.nextBoolean());
System.out.println(threadLocalRandom.nextFloat());
System.out.println(threadLocalRandom.nextDouble());
System.out.println(threadLocalRandom.nextDouble(100));
System.out.println(threadLocalRandom.nextDouble(5,87));
System.out.println(threadLocalRandom.nextInt());
System.out.println(threadLocalRandom.nextInt(45));
System.out.println(threadLocalRandom.nextInt(6,73));
System.out.println(threadLocalRandom.nextLong());
System.out.println(threadLocalRandom.nextLong(97L));
System.out.println(threadLocalRandom.nextLong(2L,64L));
System.out.println(threadLocalRandom.nextGaussian());
}
}
- 以上都是伪随机数,若要获取正随机数,可以使用SecureRandom
java.math.BigInteger
BigInteger b1 = new BigInteger("1651613541643161548462623033");
BigInteger b2 = new BigInteger("61345596529652641626261843");
// 第二个参数表示进制
BigInteger b3 = new BigInteger("12655", 16);
BigInteger bigAdd = b1.add(b2);
System.out.println(bigAdd);
BigInteger bigMinus = b1.subtract(b2);
System.out.println(bigMinus);
BigInteger bigMultiply = b1.multiply(b2);
System.out.println(bigMultiply);
BigInteger bigDivide = b1.divide(b2);
System.out.println(bigDivide);
BigInteger bigMod = b1.mod(b2);
System.out.println(bigMod);
java.math.BigDecimal
System.out.println(0.09 + 0.01);// 0.09999999999999999
System.out.println(1.0 - 0.32);// 0.6799999999999999
System.out.println(1.015 * 100);// 101.49999999999999
System.out.println(1.301 / 100);// 0.013009999999999999
System.out.println("--------------------------------------");
BigDecimal b1 = new BigDecimal("0.09");
BigDecimal b2 = new BigDecimal("0.01");
BigDecimal bigAdd = b1.add(b2);
System.out.println(bigAdd);
BigDecimal b3 = new BigDecimal("1.0");
BigDecimal b4 = new BigDecimal("0.32");
BigDecimal bigMinus = b3.subtract(b4);
System.out.println(bigMinus);
BigDecimal b5 = new BigDecimal("1.015");
BigDecimal b6 = new BigDecimal("100");
BigDecimal bigMultiply = b5.multiply(b6);
System.out.println(bigMultiply);
BigDecimal b7 = new BigDecimal("1.301");
BigDecimal b8 = new BigDecimal("100");
BigDecimal b9 = new BigDecimal("101");
BigDecimal bigDivide1 = b7.divide(b8);
System.out.println(bigDivide1);
BigDecimal bigDivide2 = b7.divide(b9, 2, BigDecimal.ROUND_HALF_EVEN);
System.out.println(bigDivide2);
四、JDK8以前的日期API
java.util.Date,java.text.SimpleDateFormat
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) {
// 获取操作系统当前日期时间
Date date = new Date();
System.out.println(date);
// Date->long
// 获取自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
long t = date.getTime();
System.out.println("从1970年1月1日00:00:00 GMT至此刻经过的毫秒数:" + t);
// long->Date
date.setTime(t);
System.out.println(date);
// Date->String
// 使用SimpleDateFormat格式化日期
// G表示公元纪年,y表示年,M表示月,d表示日,D表示一年中的第几天,w表示一年中的第几周,E表示星期几,z表示时区
// HH表示24小时制(0-23),hh表示12小时制(1-12),mm表示分钟,ss表示秒,SS表示毫秒,aa表示A.M./P.M.
// CST, China Standard Time
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd E HH:mm:ss z");
String timeStr = sdf.format(date);
System.out.println(timeStr);
// String->Date
// 解析字符串为时间
try {
date = sdf.parse(timeStr);
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
- 使用printf()显示日期和时间,不好写,容易出错,不推荐。
Date date = new Date();
long t = date.getTime(); // 下面的date可以t代替
System.out.printf("日期和时间:%tc%n", date);
// %ty--2位年份
// %tY--4位年份
// %tm--月份
// %tb--月份简称
// %tB--月份全称
// %td--日期
// %ta--星期简称
// %tA--星期全称
// %tF--%tY-%tm-%td
// %tD--%tm/%td/%ty
System.out.printf("YYYY-MM-DD:%tF%n", date);
System.out.printf("YYYY-MM-DD:%1$tY-%1$tm-%1$td%n", date);
// System.out.printf("YYYY-MM-DD:%tY-%tm-%td%n",date); //报错,占位符多于参数时需要特别指明
System.out.printf("MM/DD/YY:%tD%n", date);
System.out.printf("MM/DD/YY:%1$tm/%1$td/%1$ty%n", date);
System.out.printf("%1$ta,%1$tA%n", date);
// %tI--时,12小时制
// %tH--时,24小时制
// %tM--分
// %tS--秒
// %tL--毫秒
// %tp--上午/下午
// %tT--%tH:%tM:%tS
// %tr--%tI:%tM:%tS %p
// %tR--%tH:%tM
System.out.printf("HH:MM:SS(24):%tT%n", date);
System.out.printf("HH:MM:SS(24):%1$tH:%1$tM:%1$tS%n", date);
System.out.printf("HH:MM:SS(12 A.M./P.M.):%tr%n", date);
System.out.printf("HH:MM:SS(12 A.M./P.M.):%1$tI:%1$tM:%1$tS %1$tp%n", date);
System.out.printf("HH:MM(24):%tR%n", date);
System.out.printf("HH:MM(24):%1$tH:%1$tM%n", date);
System.out.printf("HH:MM:SS:LL(24):%1$tH:%1$tM:%1$tS:%1$tL%n", date);
java.util.Calendar
- GregorianCalendar类是Calendar的一个具体实现
import java.util.Calendar;
import java.util.Date;
public class CalendarDemo {
public static void main(String[] args) {
// 使用默认时区和语言环境获得一个日历对象
Calendar c = Calendar.getInstance();
System.out.println(c);
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) + 1;
int date = c.get(Calendar.DATE); // Calendar.MONTH==Calendar.DAY_OF_MONTH
int hour = c.get(Calendar.HOUR_OF_DAY); // 24小时制
int minute = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
int day = c.get(Calendar.DAY_OF_WEEK); // 获得星期几(注意这个与Date类是不同的,1代表星期日、2代表星期1,以此类推)
// 设置日期,以年月日为例
c.set(2009, 8 - 1, 12); // 在Calendar类中月份用0-11表示!!!但日期和年份是从1开始的
c.set(Calendar.YEAR, 2009);
c.set(Calendar.MONTH, 8 - 1);
c.set(Calendar.DATE, 12);
// 修改日期
c.add(Calendar.DATE, 10); // c1的日期加上10天
c.add(Calendar.DATE, -7); // c1的日期减去7天
c.add(Calendar.HOUR, 3); // c1加上3个小时
c.add(Calendar.HOUR, -5); // c1减去5个小时
// Calendar->Date
Date d = c.getTime();
// 判断闰年:日历设置到指定年份的3月1日,add向前偏移1天,获取天数,29闰年
c.set(2088, 3-1, 1);
c.add(Calendar.DAY_OF_MONTH, -1);
System.out.println(c.get(Calendar.DAY_OF_MONTH));
}
}
java.util.Locale,TimeZone
五、JDK8新特性——日期API
- 旧API转新API
// Date -> Instant:
Instant ins1 = new Date().toInstant();
// Calendar -> Instant -> ZonedDateTime:
Calendar calendar = Calendar.getInstance();
Instant ins2 = Calendar.getInstance().toInstant();
ZonedDateTime zdt = ins2.atZone(calendar.getTimeZone().toZoneId());
- 新API转旧API
// ZonedDateTime -> long:
ZonedDateTime zdt = ZonedDateTime.now();
long ts = zdt.toEpochSecond() * 1000;
// long -> Date:
Date date = new Date(ts);
// long -> Calendar:
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.setTimeZone(TimeZone.getTimeZone(zdt.getZone().getId()));
calendar.setTimeInMillis(zdt.toEpochSecond() * 1000);
六、正则表达式 Regular Expression,regex
- 正则表达式定义了字符串的模式,可以用来搜索、编辑或处理文本。
- 一个字符串其实就是一个简单的正则表达式
1.匹配规则:
字符:x
含义:代表的是字符x
例如:匹配规则为 "a",那么需要匹配的字符串内容就是 ”a”字符:\\
含义:代表的是反斜线字符'\'
例如:匹配规则为"\\" ,那么需要匹配的字符串内容就是 ”\”字符:\t
含义:制表符
例如:匹配规则为"\t" ,那么对应的效果就是产生一个制表符的空间字符:\n
含义:换行符
例如:匹配规则为"\n",那么对应的效果就是换行,光标在原有位置的下一行字符:\r
含义:回车符
例如:匹配规则为"\r" ,那么对应的效果就是回车后的效果,光标来到下一行行首字符类:[abc]
含义:代表的是字符a、b 或 c
例如:匹配规则为"[abc]" ,那么需要匹配的内容就是字符a,或者字符b,或字符c的一个字符类:[^abc]
含义:代表的是除了 a、b 或 c以外的任何字符
例如:匹配规则为"[^abc]",那么需要匹配的内容就是不是字符a,或者不是字符b,或不是字符c的任意一个字符字符类:[a-zA-Z]
含义:代表的是a 到 z 或 A 到 Z,两头的字母包括在内
例如:匹配规则为"[a-zA-Z]",那么需要匹配的是一个大写或者小写字母字符类:[0-9]
含义:代表的是 0到9数字,两头的数字包括在内
例如:匹配规则为"[0-9]",那么需要匹配的是一个数字字符类:[a-zA-Z_0-9]
含义:代表的字母或者数字或者下划线(即单词字符)
例如:匹配规则为" [a-zA-Z_0-9] ",那么需要匹配的是一个字母或者是一个数字或一个下滑线预定义字符类:.
含义:代表的是任何字符
例如:匹配规则为" . ",那么需要匹配的是一个任意字符。如果,就想使用 . 的话,使用匹配规则"\\."来实现预定义字符类:\d
含义:代表的是 0到9数字,两头的数字包括在内,相当于[0-9]
例如:匹配规则为"\d ",那么需要匹配的是一个数字预定义字符类:\w
含义:代表的字母或者数字或者下划线(即单词字符),相当于[a-zA-Z_0-9]
例如:匹配规则为"\w ",,那么需要匹配的是一个字母或者是一个数字或一个下滑线边界匹配器:^
含义:代表的是行的开头
例如:匹配规则为^[abc][0-9]$ ,那么需要匹配的内容从[abc]这个位置开始, 相当于左双引号边界匹配器:$
含义:代表的是行的结尾
例如:匹配规则为^[abc][0-9]$ ,那么需要匹配的内容以[0-9]这个结束, 相当于右双引号边界匹配器:\b
含义:代表的是单词边界
例如:匹配规则为"\b[abc]\b" ,那么代表的是字母a或b或c的左右两边需要的是非单词字符([a-zA-Z_0-9])数量词:X?
含义:代表的是X出现一次或一次也没有
例如:匹配规则为"a?",那么需要匹配的内容是一个字符a,或者一个a都没有数量词:X*
含义:代表的是X出现零次或多次
例如:匹配规则为"a*" ,那么需要匹配的内容是多个字符a,或者一个a都没有数量词:X+
含义:代表的是X出现一次或多次
例如:匹配规则为"a+",那么需要匹配的内容是多个字符a,或者一个a数量词:X{n}
含义:代表的是X出现恰好 n 次
例如:匹配规则为"a{5}",那么需要匹配的内容是5个字符a数量词:X{n,}
含义:代表的是X出现至少 n 次
例如:匹配规则为"a{5, }",那么需要匹配的内容是最少有5个字符a数量词:X{n,m}
含义:代表的是X出现至少 n 次,但是不超过 m 次
例如:匹配规则为"a{5,8}",那么需要匹配的内容是有5个字符a 到 8个字符a之间
匹配正整数:”\\d+”
匹配正小数:”\\d+\\.\\d+”
匹配负整数:”-\\d+”
匹配负小数:”-\\d+\\.\\d+”
匹配保留两位小数的正数:”\\d+\\.\\d{2}”
匹配保留1-3位小数的正数:”\\d+\\.\\d{1,3}”
匹配合法的邮箱:”[a-zA-Z_0-9]+@[a-zA-Z_0-9]+(\\.[a-zA-Z_0-9]+)+” 或者 ”\\w+@\\w+(\\.\\w+)+”
2 字符串中与正则表达式相关的常用方法
boolean matches(String regex)
String[] split(String regex)
String replaceAll(String regex, String replacement)
举例:校验qq号码.
1: 要求必须是5-15位数字
2: 0不能开头
代码演示:
String qq = "604154942";
String regex = "[1-9][0-9]{4,14}";
boolean flag2 = qq.matches(regex);举例:校验手机号码
1:要求为11位数字
2:第1位为1,第2位为3、4、5、7、8中的一个,后面9位为0到9之间的任意数字。
代码演示:
String phone = "18800022116";
String regex = "1[34578][0-9]{9}";
boolean flag = phone.matches(regex);
java.util.regex 包主要包括以下三个类:
- Pattern 类:Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattepattern 对象是一个正则表达式rn 对象。该方法接受一个正则表达式作为它的第一个参数。
- Matcher 类:Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
- PatternSyntaxException:一个非强制异常类,它表示一个正则表达式模式中的语法错误。
import java.util.regex.*;
public class RegexDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
String pattern = ".*wiki.*";
String content = "https://www.wikipedia.org/";
//判断content中是否含有字符串wiki
System.out.println(Pattern.matches(pattern, content));
}
}
七、工具类
java.util.Objects
toString
hashCode
equals
deepEquals
compare
isNull
nonNull
requireNonNull
requireNonNullElse
requireNonNullElseGet
java.util.Arrays
java.util.Collections
参考书籍:《疯狂Java讲义》