1.2工具类
1.数学类
(1)Math
求绝对值:
Math.abs(-100); // 100
Math.abs(-7.8); // 7.8
取最大或最小值:
Math.max(100, 99); // 100
Math.min(1.2, 2.3); // 1.2
计算xy次方:
Math.pow(2, 10); // 2的10次方=1024
向上取整/向下取整
Math.ceil(3.5); // 4 向上取整
Math.floor(3.5); // 3 向下取整
(2)Random:生成伪随机数
Random r = new Random();
r.nextInt(); // [0,2071575453),每次都不一样
r.nextInt(10); // 生成一个[0,10)之间的int
r.nextLong(); // [0,8811649292570369305),每次都不一样
r.nextFloat(); // 0.54335...生成一个[0,1)之间的float
r.nextDouble(); // 0.3716...生成一个[0,1)之间的double
(3)SecureRandom:生成安全的随机数
public class Main {
public static void main(String[] args) {
SecureRandom sr = null;
try {
sr = SecureRandom.getInstanceStrong(); // 获取高强度安全随机数生成器
} catch (NoSuchAlgorithmException e) {
sr = new SecureRandom(); // 获取普通的安全随机数生成器
}
byte[] buffer = new byte[16];
sr.nextBytes(buffer); // 用安全随机数填充buffer
System.out.println(Arrays.toString(buffer));
}
}
2.字符串类
(1)String
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
...
}
①概念
- final修饰,不可被继承
- 实现了序列化接口,支持跨进程访问。实现Comparable、CharSequence接口、
- 底层实现:
- jdk8:char value[]
- jdk9:byte value[]
②不可变性:在对字符串进行赋值、拼接、调用api操作时,需要重新分配内存而不是更改原字符串对象
(Ⅰ)赋值:仅当字符串常量池内还没有当前要创建的字符串常量时才会在里面配内存
(i)字面量方式:在字符串常量池分配内存
String str = “a”;
第二次赋值:String str = new String(“b”)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b26mhdgO-1686210934891)(C:\Users\10059\AppData\Roaming\Typora\typora-user-images\image-20220110141745924.png)]
(ii)new对象方式:在堆和字符串常量池分配内存
String str = new String(“a”)
第二次赋值:str = “b”
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BJ98hAHS-1686210934894)(C:\Users\10059\AppData\Roaming\Typora\typora-user-images\image-20220110141901181.png)]
(Ⅱ)拼接:底层原理为StringBuilder.append.append.toString
/**
* 测试代码
*/
public class Test {
public static void main(String[] args) {
int i = 10;
String s = "abc";
System.out.println(s + i);
}
}
/**
* 反编译后
*/
public class Test {
public static void main(String args[]) { //删除了默认构造函数和字节码
byte byte0 = 10;
String s = "abc";
System.out.println((new StringBuilder()).append(s).append(byte0).toString());
}
}
//使用“+”连接符时,JVM会隐式创建StringBuilder对象,这种方式在大部分情况下并不会造成效率的损失,不过在进行大量循环拼接字符串时则需要注意。
String s = "abc";
for (int i=0; i<10000; i++) {
s += "abc";
}
/**
* 反编译后
*这样由于大量StringBuilder创建在堆内存中,肯定会造成效率的损失,所以在这种情况下建议在循环体外创建一个 StringBuilder对象调用append()方法手动拼接(如上面例子如果使用手动拼接运行时间将缩小到1/200左右)。
*/
String s = "abc";
for(int i = 0; i < 1000; i++) {
s = (new StringBuilder()).append(s).append("abc").toString();
}
/**
* 循环中使用StringBuilder代替“+”连接符
*/
StringBuilder sb = new StringBuilder("abc");
for (int i = 0; i < 1000; i++) {
sb.append("abc");
}
sb.toString();
(i)字面量和字面量:结果在字符串常量池里
(ii)只要出现字符串变量:结果在堆里,并且最后的拼接结果不会在字符串常量池出现
(Ⅲ)调用api:结果在堆里。因为不可变性重新分配内存,调用完api都会新生成一个对象
③intern方法
- 当前操作的字符串在字符串常量池里面已经存在:返回字符串常量的引用
- 当前操作的字符串在字符串常量池里面没存在:会将此String对象在字符串常量池中创建一个,然后返回此String对象的引用
static final int MAX = 1000 * 10000;
static final String[] arr = new String[MAX];
//未使用intern,耗时826ms:占用了大约640m 空间
//使用intern,耗时2160ms;gc掉大部分在堆中不可达的实例对象,占用总空间 133k 左右
public static void main(String[] args) throws Exception {
Integer[] DB_DATA = new Integer[10];
Random random = new Random(10 * 10000);
for (int i = 0; i < DB_DATA.length; i++) {
DB_DATA[i] = random.nextInt();
}
long t = System.currentTimeMillis();
for (int i = 0; i < MAX; i++) {
//arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length]));
arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length])).intern();
}
System.out.println((System.currentTimeMillis() - t) + "ms");
System.gc();
}
(2)StringBuffer,StringBuilder
①继承结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RB8uqhwp-1686210934895)(C:\Users\10059\AppData\Roaming\Typora\typora-user-images\image-20220110161329911.png)]
②主要区别
- String是不可变字符串序列,StringBuffer和StringBuilder是可变字符串序列
- StringBuffer是线程安全的,StringBuilder是线程不安全的
- 执行速度StringBuilder > StringBuffer > String
(3)正则表达式API
①String类
//1.验证匹配
String str = "123";
String regex = "1[38]\\d{9}";
boolean result = str.matches(regex);
②Pattern类
//1.创建Pattern
String regex = "1[38]\\d{9}";
Pattern pattern = Pattern.compile(regex);//args:字符串形式的正则表达式
//2.1 创建Matcher,验证匹配
String str = "123";
Matcher matcher = pattern.matcher(str);//args:需要验证匹配的字符串
matcher.matches()
//2.2 验证匹配
Boolean result = Pattern.matches(regex,str);
③Matcher类
- matches():判断整个字符串是否匹配
- find():查找匹配的
子字符串
,找到一个就返回true。如果有多个要和while一起用 - appendReplement(StringBuffer sb, String)/appendtail(StringBuffer sb):和find()方法一起用
- appendReplement:替换到最后一次匹配的位置,丢失后面的字符串。将替换后的结果赋值给sb
- appendTail:将丢失的字符串拼接回来。将结果赋值给sb
- group(int):在调用之前必须调用一次find()方法
- group(0):返回整个匹配的
子字符串
- group(1):返回匹配子字符串的
第一个子表达式
的字符串(子表达式“()“,一定要带())。如果一个都没有就会报错
- group(2):返回匹配子字符串的
第二个子表达式
的字符串(子表达式“()“,一定要带()) - 。。。
- group(0):返回整个匹配的
- start()/end():在调用之前必须调用一次find()方法
- start:返回匹配的
子字符串
在原字符串中的起始位置 - end:返回匹配的
子字符串
在原字符串中的结束位置
- start:返回匹配的
//1.验证匹配,整个字符串要匹配返回true,如果只是子串匹配没有用
matcher.matches();
//2.查找:找到第一个匹配的子串就返回true,如果有多个匹配的要和while配合使用
matcher.find();
//3.替换
//3.1生成 Pattern 对象并且编译一个简单的正则表达式"cat"
Pattern p = Pattern.compile("cat");
//3.2用 Pattern 类的 matcher() 方法生成一个 Matcher 对象
Matcher m = p.matcher("fatcatfatcatfat");
StringBuffer sb = new StringBuffer();
while(m.find()){
//3.2.1此时sb为fatdogfatdog,cat被替换为dog,并且将最后匹配到之前的子串都添加到sb对象中
m.appendReplacement(sb,"dog");
}
//3.3此时sb为fatdogfatdog,将最后匹配到后面的子串添加到sb对象中
m.appendTail(sb);
//3.4输出内容为fatdogfatdogfat
System.out.println("sb:"+sb);
//4.分组匹配
String matcher.group(int group)
//4.1正则表达式中以’()’标记的子表达式所匹配的内容就是一个分组(group).
//4.2如果正则表达式中没有以’()’标记的子表达式,那么调用m.group(1)就会报错,只能调用m.group(0)
//4.3当正则表达式包含1个或多个group时,也就是含有1个或多个’(pattern)’格式的子表达式时,它的分组索引(group number)是从1开始的,而group(0)则代表了匹配整个表达式的字符串
String text = "John writes about this, and John Doe writes about that,"
+ " and John Wayne writes about everything.";
String patternString1 = "(John) (.+?) ";
Pattern pattern = Pattern.compile(patternString1);
Matcher matcher = pattern.matcher(text);
int start = matcher.start();//返回当前匹配到的字符串在原目标字符串中的位置
int end = matcher.end();//返回当前匹配的字符串的最后一个字符在原目标字符串中的索引位置
System.out.println("found group: group(0) is '" + matcher.group(0));
System.out.println("found group: group(1) is '" + matcher.group(1) + "',group(2) is '" + matcher.group(2)+"'");
3.时间日期类
- Date
- Calendar
- LocalDate、LocalTime、LocalDateTime
4.格式化类
- DecimalFormat
- SimpleDateFormat
- DateTimeFormat
5.数组集合工具类
(1)Arrays:
①以字符串形式打印数组:toString
//以字符串形式打印数组,toString
String[] strArr = {"a","b","c"};
System.out.println(Arrays.toString(strArr));// [a, b, c]
②根据数组创建List:asList
//根据数组创建ArrayList:asList
String[] strArr2 = {"a","b","c"};
List<String> stringList = Arrays.asList(strArr2);
(2)Collections:
①创建空集合:emptyList(),emptySet(),emptyMap()
它继承AbstractList后并没有实现add()、remove()等方法,因此这个返回值List并不能增加删除元素。
如果直接拿它去调用,会报错 java.lang.UnsupportedOperationException。emptySet(),emptyMap()同理
//在写方法的时候可能结果集不存在,需要返回null,在调用这个方法的地方就要做一个null判断,很繁琐,容易出问题,这个时候就可以使用emptyList。如果用new ArrayList也可以,但是每次new 一个集合对象的时候都会有一个初始化空间,占用内存资源,积少成多会浪费很多的资源,Collections中的空集合对象是一个静态常量,在内存中只存在一份,所以能够节省内存资源。在可能返回空列表的时候使用。emptySet(),emptyMap()同理
public List<String> list = Collections.emptyList();
public Set<String> set = Collections.emptySet();
public Map<String,String> map = Collections.emptyMap();
Test test = new Test();
// test.list = new ArrayList<>(); 没有这一句的话就报错
test.list.add("1");
②创建不可变单例集合:singletonList(),singleton(),singletonMap()
//Collections.singletonList()返回的是不可变的静态集合,但是这个长度的集合只有1,可以减少内存空间。但是返回的值依然是Collections的内部实现类,同样没有add的方法,调用add,set方法会报错。singleton()和singletonMap()同理
public List<String> singletonList = Collections.singletonList("1");
public Set<String> singletonSet = Collections.singleton("1");
public Map<String, String> singletonMap = Collections.singletonMap("1","1");
ingletonList()返回的是不可变的静态集合,但是这个长度的集合只有1,可以减少内存空间。但是返回的值依然是Collections的内部实现类,同样没有add的方法,调用add,set方法会报错。singleton()和singletonMap()同理
public List singletonList = Collections.singletonList(“1”);
public Set singletonSet = Collections.singleton(“1”);
public Map<String, String> singletonMap = Collections.singletonMap(“1”,“1”);