常用工具类
## 字符串
### String
字符串是程序开发中使用的很多的一种类型,String 不是基本数据类型,但是又可以和基本数据类型包装类一样可以直接赋值来使用,所以这个类有点特殊
```java
package com.classes;
import java.util.Arrays;
import java.util.Calendar;
public class StringTest {
public static void main(String[] args) {
/*
* 和基本数据类型装箱和拆箱是有区别的
* String中有一个char数组 使用了final修饰 所以String是不可变的
* String类本身使用了final修饰,这个类就不能被继承
* String的构造本质上就是在给value char数组赋值
*/
String str = "abc";//abc存在于常量池中,然后内存地址赋值给str
String str2 = new String("abc"); // abc存在于常量池中,堆中开辟了空间存放了abc的引用,然后把堆中的引用赋值给str2
//可以通过char数组创建对象
// String str3 = new String(chars);
//可以将byte数组通过指定的编码创建对象 UTF-8
// new String(bytes,charset);
String fileName = "ajklgsdfhpOAaDSF.jpg";
//字符串的长度
int length = fileName.length();
//将字符串转换成byte数组
byte[] bytes = fileName.getBytes();
//将字符串以指定的编码转换成byte数组
// byte[] bytes2 = fileName.getBytes("ISO-8859-1");
//将字符串转换为char数组
char[] charArray = fileName.toCharArray();
//拼接字符串,返回拼接后的结果
// fileName.concat(str2)
//判断字符串中是否包含指定的字符串
boolean contains = fileName.contains("a");
//返回字符串中指定索引的char值
// char c = fileName.charAt(index)
//判断是否以指定的字符串结尾
// fileName.endsWith(suffix)
//判断是否以指定的字符串开头
// fileName.startsWith(prefix)
//字符串判断相等使用equals
// fileName.equals(anObject)
//忽略大小写比较是否相同
// fileName.equalsIgnoreCase(anotherString)
//从左往右返回指定的字符串在原字符串的索引 如果不存在返回-1
int indexOf = fileName.indexOf("s");
//从指定的位置开始 从左往右返回指定的字符串在原字符串的索引 如果不存在返回-1
// fileName.indexOf(ch, fromindex)
//从右往左 返回指定的字符串在原字符串的索引 如果不存在返回-1
// fileName.lastIndexOf(str2)
//从指定的位置开始 从右往左 返回指定的字符串在原字符串的索引 如果不存在返回-1
// fileName.lastIndexOf(str2, fromIndex)
//是否为空的字符串 ""
// fileName.isEmpty()
//匹配正则表达式
// fileName.matches(regex)
//替换字符串 使用new替换old 返回替换后的结果
// fileName.replace(oldChar, newChar)
//支持正则表达式替换
// fileName.replaceAll(regex, replacement)
//以指定的符号分割字符串 如果分割的字符串在最前面会留下空串 如果在最后就不会留下空串
String[] split = fileName.split("a");
System.out.println(Arrays.toString(split));
// 从指定的位置开始到末尾截取字符串
// fileName.substring(beginIndex)
// 从指定的位置开始到指定的位置结束 截取字符串
// fileName.substring(beginIndex, endIndex)
//转换成小写
// fileName.toLowerCase()
//转换为大写
// fileName.toUpperCase()
//去除字符串的首尾空格
// fileName.trim()
//从char数组中复制出来转换为字符串
// String.copyValueOf(data)
// 从char数组中指定位置复制指定长度 转换为字符串
// String.copyValueOf(data, offset, count)
//格式化字符串 了解为主
Calendar c = Calendar.getInstance();
String s1 = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
System.out.println(s1);
}
}
StringBuilder,StringBuffer
因为String是无法改变的,所以在操作字符串的时候提供了StringBuilder,StringBuffer来进行操作
package com.classes;
public class StringBuilderTest{
public static void main(String[] args) {
// String str = "";
StringBuilder buffer = new StringBuilder();
//当前时间的毫秒数 时间戳 格林威治时间 1970-1-1 0:0:0 到现在时间的毫秒数
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
// str += i + "";
buffer.append(i);
}
System.out.println(System.currentTimeMillis() - start);
}
public static void test(){
/*
都是可变字符串 里面有一个char数组 没有使用final来进行修饰
换句话来说这个char数组是可变的
使用无参构造的时候默认都会去创建长度为16的数组
StringBuffer中的方法都添加了关键字 synchronized 所以线程安全
StringBuilder中的方法没有添加 所以线程不安全
在单线程的情况下,如果不涉及线程安全的情况下 建议使用 StringBuilder
在多线程的情况下,如果涉及到线程安全 建议使用StringBuffer
*/
StringBuilder builder = new StringBuilder();
StringBuffer buffer = new StringBuffer();
//添加内容 往末尾添加内容 有很多重载的append方法
buffer.append("asdasd");
//返回数组的长度
buffer.capacity();
// 返回指定索引的char
// buffer.charAt(index)
//删除从start开始到end结束的字符内容 删除的内容包含start不包含end
buffer.delete(1, 3);
//添加内容到指定的位置上面
buffer.insert(1, "qqqq");
//删除指定位置上面的字符
buffer.deleteCharAt(0);
//从左往右 找指定字符串出现的索引 如果没找到返回-1
// buffer.indexOf(str);
//从指定的位置开始 从左往右找指定字符串出现的索引 如果没找到返回-1
// buffer.indexOf(str, fromIndex);
//从右往左 找指定字符串出现的索引 如果没找到返回-1
// buffer.lastIndexOf(str);
//从右往左 从指定的位置开始 找指定字符串出现的索引 如果没找到返回-1
// buffer.lastIndexOf(str, fromIndex);
//字符串的长度
buffer.length();
//颠倒字符串
buffer.reverse();
System.out.println(buffer);
}
}
面试题:String,StringBuilder,StringBuffer的区别是什么?
String是不可变的 原因是内部的char数组使用了final修饰
StringBuilder,StringBuffer 是可变的 里面的数组没有使用final修饰
StringBuilder是线程不安全的 效率更高
StringBuffer中的方法 使用了synchronized关键字 所以是线程安全的 效率相对较低
拼接字符串不要使用+直接去拼接String
面试题:String a = “a”; String b = “b”;String c = a + b;
在源程序中使用了"+“,但在编译时仍然将”+“转换成 StringBuilder。因此,我们可以得出结论,在 Java 中无论使用何种方式进行字符串连接,实际上都使用的是 StringBuilder。虽然编译器将”+"转换成了 StringBuilder 分析下面的代码 javaString s = "abc";String ss = "ok" + s + "xyz" + 5;System.out.println(ss);
上面的代码感觉没有什么奇怪的现象,且从表面上看,对字符串和整型使用"+"号并没有什么区别 我们来看看上面代码的本质,介绍JDK自带`jad`工具,此工具能将`.class`文件进行反编译成`Java Byte Code`,执行命令 ```jad -o -a -s d.java TestSimple.class```反编译后代码如下 ```javaString s = "abc";String ss = (new StringBuilder("ok")).append(s).append("xyz").append(5).toString();System.out.println(ss);```使用jad反编译的好处之一就是可以同时生成字节码和源代码。这样可以进行对照研究。从上面的代码很容易看出,虽然在源程序中使用了"+",但在编译时仍然将"+"转换成StringBuilder。因此,我们可以得出结论,**在Java中无论使用何种方式进行字符串连接,实际上都使用的是StringBuilder** 如果使用循环来连接字符串,那么产出的`Java Byte Code`就会有很大区别 ```javaString s = "";Random rand = new Random();for (int i = 0; i < 10; i++){ s = s + rand.nextInt(1000) + " ";}System.out.println(s);```上面的代码返编译后的`Java Byte Code`如下 ```javaString s = "";Random rand = new Random();for(int i = 0; i < 10; i++) s = (new StringBuilder(String.valueOf(s))).append(rand.nextInt(1000)).append(" ").toString();System.out.println(s); 大家可以看到,虽然编译器将"+"转换成了StringBuilder,但创建StringBuilder对象的位置却在for语句内部。这就意味着每执行一次循环,就会创建一个StringBuilder对象(对于本例来说,是创建了10个StringBuilder对象),虽然Java有垃圾回收器,但这个回收器的工作时间是不定的。如果不断产生这样的垃圾,那么仍然会占用大量的资源。解决这个问题的方法就是在程序中直接使用StringBuilder来连接字符串,代码如下 ```javaRandom rand = new Random();StringBuilder result = new StringBuilder();for (int i = 0; i < 10; i++){ result.append(rand.nextInt(1000)); result.append(" ");}System.out.println(result.toString());```注意: - 在使用StringBuilder时要注意,尽量不要"+"和StringBuilder混着用,否则会创建更多的StringBuilder对象- StringBuffer和StringBuilder的功能基本一样,只是StringBuffer是线程安全的,而StringBuilder不是线程安全的。因此,StringBuilder的效率会更高
Random
package com.classes;
import java.util.Random;
public class RandomTest {
public static void main(String[] args) {
//产生伪随机数
Random random = new Random();//根据时间产生了一个随机种子
//产生指定类型的随机数
random.nextBoolean();
random.nextDouble();
random.nextFloat();
random.nextLong();
Random random1 = new Random(10);//指定了一个随机数种子
Random random2 = new Random(10);//指定了一个随机数种子
//如果random的随机数种子一样则产生的随机数是可以预测的
for (int i = 0; i < 10; i++) {
//产生一个int的随机数
// System.out.println(random1.nextInt() + "===" + random2.nextInt());
//产生一个指定范围的随机数
System.out.println(random1.nextInt(10) + "===" + random2.nextInt(10));
}
}
}
Math
里面包含了很多关于数学的一些操作,主要包含了一些静态的方法
package com.classes;
public class MathTest {
public static void main(String[] args) {
// 最接近于圆周率的一个常量
// Math.PI
// 自然底数
// Math.E
//取绝对值
// Math.abs(a)
//三角函数
// Math.sin(a)
// Math.cos(a)
// Math.tan(a)
// Math.asin(a)
// Math.acos(a)
// Math.atan(a)
//开立方
// Math.cbrt(a)
//开平方
// Math.sqrt(a)
//向上取整 返回大于等于它的最小整数
System.out.println(Math.ceil(3.14));
//向下取整 返回小于等于它的最大整数
// Math.floor(a)
//求较大值
// Math.max(a, b)
//求较小值
// Math.min(a, b)
//返回a的b次方
// Math.pow(a, b)
//产生一个0-1之间的随机数
Math.random();
// 要产生一个a-b之间的随机整数 包含a不包含b
// (int)(Math.random() * (b - a)) + a
//四舍五入 返回int
// Math.round(a)
}
}
System
系统类,包含了一些跟程序相关的操作
package com.classes;
public class SystemTest {
public static void main(String[] args) {
//输入流 源为控制台
// System.in
// 输出流 目的地为控制台
// System.out
//输出流 输出的内容是红色的
// System.err
//当前时间的时间戳
System.currentTimeMillis();
//当前时间的纳秒数
System.nanoTime();
// 垃圾回收通知垃圾回收线程这里有垃圾要进行回收 一般还是不建议使用
System.gc();
//退出虚拟机 0 正常退出 -1 异常退出
// System.exit(status);
//数组拷贝 是一个本地方法
int [] a = {1,2,3,4,5,6,7,8,9};
int [] b = new int[20];
// 从a的第0个开始复制 到b的第0个开始 共复制a.length 个数据
System.arraycopy(a, 0, b, 10, a.length);
for (int i = 0; i < b.length; i++) {
System.out.println(b[i]);
}
}
}
Date,SimpleDateFormat
字母 日期或时间元素 表示 示例
G Era 标志符 Text AD
y 年 Year 1996; 96
M 年中的月份 Month July; Jul; 07
w 年中的周数 Number 27
W 月份中的周数 Number 2
D 年中的天数 Number 189
d 月份中的天数 Number 10
F 月份中的星期 Number 2
E 星期中的天数 Text Tuesday; Tue
a Am/pm 标记 Text PM
H 一天中的小时数(0-23) Number 0
k 一天中的小时数(1-24) Number 24
K am/pm 中的小时数(0-11) Number 0
h am/pm 中的小时数(1-12) Number 12
m 小时中的分钟数 Number 30
s 分钟中的秒数 Number 55
S 毫秒数 Number 978
z 时区 General time zone Pacific Standard Time; PST; GMT-08:00
Z 时区 RFC 822 time zone -0800
package com.classes;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTest {
public static void main(String[] args) {
//创建一个当前时间的Date对象
Date date = new Date();
//通过一个时间戳来创建对象
// date = new Date(2490562456l);
Date date2 = new Date(2490562457l);
//判断两个Date描述的时间谁在前,谁在后
boolean after = date.after(date2);
boolean before = date.before(date2);
System.out.println(before);
//返回Date描述时间的时间戳
long time = date.getTime();
// 如果直接使用date来进行打印针对很多中国是不友好 Fri Jan 30 03:49:22 CST 1970
// 格式化日期
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM-dd HH:mm:ss E");
// 将Date转换为指定格式的字符串
String format = dateFormat.format(date);
// 将指定格式的字符串转换为Date对象 字符串的格式必须和format中指定的格式一致
Date parse = null;
try {
parse = dateFormat.parse("2021年07-20 14:35:31 星期二");
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(parse);
}
}
Calendar
日历类,替换了Date中的很多方法
package com.classes;
import java.util.Calendar;
import java.util.Date;
public class CalendarTest {
public static void main(String[] args) {
//获取一个日历的对象 指定的时间为当前时间
Calendar calendar = Calendar.getInstance();
//返回Date类型的对象
Date time = calendar.getTime();
//把date转换为日历对象
// calendar.setTime(date);
// 判断 Calendar 对象谁在前,谁在后
// calendar.after(when);
// calendar.before(when);
System.out.println(time);
//在指定的格式上添加指定的时间
// calendar.add(Calendar.MONTH, 10);
//将指定的格式设置位指定的时间 月份从0开始计算
// calendar.set(Calendar.DAY_OF_MONTH, 18);
// 获取指定格式上的时间的值
int i = calendar.get(Calendar.DAY_OF_WEEK);
System.out.println(i);
time = calendar.getTime();
System.out.println(time);
/*
日历类中有很多常量是需要记忆的
Calendar.YEAR 年
Calendar.MONTH 月
Calendar.DAY_OF_MONTH 月中的天数
Calendar.HOUR 12小时
Calendar.HOUR_OF_DAY 24小时
Calendar.MINUTE 分
Calendar.SECOND 秒
Calendar.MILLISECOND 毫秒
Calendar.DAY_OF_WEEK 星期几 第一天是星期日
Calendar.DAY_OF_YEAR 一年中的第几天
*/
}
}
BigInteger,BigDecimal
面试题:计算两个Long的最大值相加
BigInteger的使用
package com.classes;
import java.math.BigInteger;
public class BigIntegerTest {
public static void main(String[] args) {
/*
* BigInteger 里面存放的是整数
*/
BigInteger bigInteger = new BigInteger(-Long.MAX_VALUE + "");
BigInteger bigInteger2 = new BigInteger(Long.MAX_VALUE + "");
//加法运算
BigInteger add = bigInteger.add(bigInteger2);
//减法运算
BigInteger subtract = bigInteger.subtract(bigInteger2);
//乘法运算
BigInteger multiply = bigInteger.multiply(bigInteger2);
//除法运算
BigInteger divide = bigInteger.divide(bigInteger2);
//取模运算
BigInteger mod = bigInteger.mod(bigInteger2);
//返回较大的BigInteger
BigInteger integer = bigInteger.max(bigInteger2);
//返回较小的BigInteger
BigInteger min = bigInteger.min(bigInteger2);
//取反
BigInteger negate = bigInteger.negate();
//当前bigInteger的指定次幂
BigInteger pow = bigInteger.pow(Integer.MAX_VALUE);
//左移n位 << n
// bigInteger.shiftLeft(n)
//右移 >> n
// bigInteger.shiftRight(n)
//返回当前对象的绝对值
BigInteger abs = bigInteger.abs();
System.out.println(pow);
}
}
BigDecimal的使用
package com.classes;
import java.math.BigDecimal;
public class BigDecimalTest {
public static void main(String[] args) {
//存放很庞大的小数
BigDecimal bigDecimal = new BigDecimal("3.14");
BigDecimal bigDecimal2 = new BigDecimal("3.14");
BigDecimal add = bigDecimal.add(bigDecimal2);
BigDecimal subtract = bigDecimal.subtract(bigDecimal2);
BigDecimal multiply = bigDecimal.multiply(bigDecimal2);
BigDecimal divide = bigDecimal.divide(bigDecimal2);
//取模
BigDecimal remainder = bigDecimal.remainder(bigDecimal2);
//绝对值
BigDecimal abs = bigDecimal.abs();
//小数点往左移动n位
// bigDecimal.movePointLeft(n)
//小数点往右移动n位
// bigDecimal.movePointRight(n)
//返回当前对象的n次幂
// bigDecimal.pow(n)
}
}
System.out.println(pow);
}
}
BigDecimal的使用
```java
package com.classes;
import java.math.BigDecimal;
public class BigDecimalTest {
public static void main(String[] args) {
//存放很庞大的小数
BigDecimal bigDecimal = new BigDecimal("3.14");
BigDecimal bigDecimal2 = new BigDecimal("3.14");
BigDecimal add = bigDecimal.add(bigDecimal2);
BigDecimal subtract = bigDecimal.subtract(bigDecimal2);
BigDecimal multiply = bigDecimal.multiply(bigDecimal2);
BigDecimal divide = bigDecimal.divide(bigDecimal2);
//取模
BigDecimal remainder = bigDecimal.remainder(bigDecimal2);
//绝对值
BigDecimal abs = bigDecimal.abs();
//小数点往左移动n位
// bigDecimal.movePointLeft(n)
//小数点往右移动n位
// bigDecimal.movePointRight(n)
//返回当前对象的n次幂
// bigDecimal.pow(n)
}
}