CommonClass
一、String两种创建方式
String str = "123";
创建的str对象直接指向常量池中的"123"
String str = new String("123");
//构造函数
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
创建的str对象指向堆中的value字符数组,堆中的value数组再指向常量池中的"123"
//String.intern() --> 对于new创建的字符串返回字符数组value指向的常量池的地址
@Test
public void newString(){
String str1 = "123";
String str2 = new String("123");
System.out.println(str1 == str2); //false
System.out.println(str1.equals(str2)); //true
System.out.println(str1 == str2.intern()); //true
System.out.println(str2 == str2.intern()); //false
}
由于存储字符串内容的字符数组被final修饰,每次更改字符串内容时相当于创建一个新字符串然
后指向新的地址
String str = "123";
System.out.println(str.hashCode()); //48690
str += "1";
System.out.println(str.hashCode()); //1509439
二、StringBuffer
//StringBuffer构造函数
public StringBuffer() {
super(16); //super(16);
}
public StringBuffer(int capacity) {
super(capacity);
}
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
//AbstractStringBuilder构造函数
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
默认创建StringBuffer容量为16,如果传入参数则容量为参数的长度 + 16
@Test
public void newStringBuffer(){
StringBuffer stringBuffer1 = new StringBuffer();
StringBuffer stringBuffer2 = new StringBuffer("asd");
System.out.println(stringBuffer1.capacity()); //16
System.out.println(stringBuffer2.capacity()); //19
}
增删查改方法:
@Test
public void test(){
StringBuffer stringBuffer = new StringBuffer();
//添加
stringBuffer.append("123456");
System.out.println(stringBuffer.toString());
//插入
stringBuffer.insert(2, "abc");
System.out.println(stringBuffer.toString());
//修改 [)
stringBuffer.replace(2, 3, "H");
System.out.println(stringBuffer.toString());
//删除 [)
stringBuffer.delete(0, 5);
System.out.println(stringBuffer.toString());
}
/*
123456
12abc3456
12Hbc3456
3456
*/
向StringBuilder中传入null值:
@Test
public void nullStr(){
String str = null;
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1.append(str);
System.out.println(stringBuffer1.length());
System.out.println(stringBuffer1);
System.out.println("-----------------------------");
StringBuffer stringBuffer2 = new StringBuffer(str);
System.out.println(stringBuffer2.length());
System.out.println(stringBuffer2);
}
/*
4
null
-----------------------------
java.lang.NullPointerException
*/
append传入null:
new StringBuilder(null):
三、StringBuilder
和StringBuffer一样,构造函数和增删查改方法相同:
@Test
public void newStringBuilder(){
StringBuilder StringBuilder1 = new StringBuilder();
StringBuilder StringBuilder2 = new StringBuilder("asd");
System.out.println(StringBuilder1.capacity()); //16
System.out.println(StringBuilder2.capacity()); //19
}
@Test
public void test(){
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("123456");
System.out.println(stringBuilder.toString());
stringBuilder.insert(2, "abc");
System.out.println(stringBuilder.toString());
stringBuilder.replace(2, 3, "H");
System.out.println(stringBuilder.toString());
stringBuilder.delete(0, 5);
System.out.println(stringBuilder.toString());
}
/*
123456
12abc3456
12Hbc3456
3456
*/
@Test
public void nullStr(){
String str = null;
StringBuilder StringBuilder1 = new StringBuilder();
StringBuilder1.append(str);
System.out.println(StringBuilder1.length());
System.out.println(StringBuilder1);
StringBuilder StringBuilder2 = new StringBuilder(str);
System.out.println(StringBuilder2.length());
System.out.println(StringBuilder2);
}
/*
4
null
-----------------------------
java.lang.NullPointerException
*/
String、StringBuilder和StringBuffer拼接字符串比较:
@Test
public void time(){
String str = "";
long start = 0L;
long end = 0L;
StringBuffer stringBuffer = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 0; i < 20_000; i++) {
stringBuffer.append(String.valueOf(i));
}
end = System.currentTimeMillis();
System.out.println("stringBuffer拼接2万次用时为:" + (end - start) + "ms");
}
//String拼接两万次用时为:830ms
@Test
public void time(){
String str = "";
long start = 0L;
long end = 0L;
StringBuilder stringBuilder = new StringBuilder();
start = System.currentTimeMillis();
for (int i = 0; i < 20_000; i++) {
stringBuilder.append(String.valueOf(i));
}
end = System.currentTimeMillis();
System.out.println("StringBuilder拼接2万次用时为:" + (end - start) + "ms");
}
//StringBuilder拼接2万次用时为:4ms
@Test
public void time(){
String str = "";
long start = 0L;
long end = 0L;
StringBuffer stringBuffer = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 0; i < 20_000; i++) {
stringBuffer.append(String.valueOf(i));
}
end = System.currentTimeMillis();
System.out.println("stringBuffer拼接2万次用时为:" + (end - start) + "ms");
}
//stringBuffer拼接2万次用时为:5ms
总结:
- 如果对String做大量修改,不要使用String,每次都会创建新的String,效率低
- StringBuffer用于多线程,所有方法前都加上Sychronized修饰符
- StringBuilder用于单线程,多线程不安全,在数据量大的情况下效率会比StringBuffer更高。
四、Arrays(数组工具类)
1.toString
int[] arr = {1, 7, 3, 5, 2, 6};
System.out.println(Arrays.toString(arr)); //遍历数组
@Test
public void toStr() {
int[] arr1 = null;
int[] arr2 = {};
System.out.println(Arrays.toString(arr1)); // "null"
System.out.println(Arrays.toString(arr2)); // "[]"
}
2.asList
@Test
public void asList() {
Integer[] arr = {1,2,4,56,2,7};
List<Integer> list = Arrays.asList(arr); //将数组转换为集合
System.out.println(list); //[1, 2, 4, 56, 2, 7]
System.out.println(list.getClass()); //class java.util.Arrays$ArrayList
}
3.sort
int[] arr = {1, 7, 3, 5, 2, 6};
Arrays.sort(arr); //将数组从小到大进行排序
System.out.println(Arrays.toString(arr)); //[1, 2, 3, 5, 6, 7]
arr = {1, 7, 3, 5, 2, 6};
Arrays.sort(arr, 1, 3); //将数组中下标[1,3)的元素从小到大进行排序
System.out.println(Arrays.toString(arr)); //[1, 3, 7, 5, 2, 6]
Integer[] arr = {1, 7, 3, 5, 2, 6};
Arrays.sort(arr, new Comparator<Integer>() { //控制排序的顺序(从大到小)
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println(Arrays.toString(arr)); //[7, 6, 5, 3, 2, 1]
4.equals
Integer[] arr = {1, 7, 3, 5, 2, 6};
Integer[] arr2 = {1, 2, 3, 5, 6, 7};
System.out.println(Arrays.equals(arr, arr2)); //false
5.fill
int[] arr = {1, 7, 3, 5, 2, 6};
Arrays.fill(arr, 0); //填充数组中的所有值
System.out.println(Arrays.toString(arr)); //[0, 0, 0, 0, 0, 0]
6.binarySearch
//二分查找
int[] arr = {1, 7, 3, 5, 2, 6};
System.out.println(Arrays.binarySearch(arr, 5)); //3
System.out.println(Arrays.binarySearch(arr, -1)); //-1 未找到
五、Collections(集合工具类)
操作List的常用方法:
@Test
public void test(){
ArrayList list = new ArrayList();
list.add("1");
list.add("null");
list.add("asd");
list.add("1.567");
list.add("true");
list.add("z");
System.out.println(list);
Collections.reverse(list); //将集合翻转
System.out.println("集合翻转:" + list);
System.out.println("----------------------------------");
for (int i = 0; i < 3; i++) {
Collections.shuffle(list); //将集合随机排序
System.out.println("集合第"+ (i + 1) +"次随机排序" + list);
}
System.out.println("----------------------------------");
Collections.sort(list); //自然顺序排序
System.out.println("集合从小到大排序:" + list);
System.out.println("----------------------------------");
Collections.sort(list, new Comparator<Object>() { //从大到小排序
@Override
public int compare(Object o1, Object o2) {
return ((String) o2).compareTo((String) o1);
}
}); //自然顺序排序
System.out.println("集合从大到小排序排序:" + list);
System.out.println("----------------------------------");
Collections.swap(list, 0, 1);
System.out.println("将集合小标为0和小标为1位置的元素交换:" + list);
System.out.println("----------------------------------");
ArrayList dest = new ArrayList();
//需要让目标集合大小 >= 源集合大小
for (int i = 0; i < list.size(); i++) {
dest.add(null);
}
Collections.copy(dest, list);
System.out.println("对集合进行拷贝:" + dest);
System.out.println("----------------------------------");
System.out.println("将集合中所有1替换为100:" + Collections.replaceAll(list, "1", "100"));
System.out.println(list);
}
/*
[1, null, asd, 1.567, true, z]
集合翻转:[z, true, 1.567, asd, null, 1]
----------------------------------
集合第1次随机排序[asd, true, null, z, 1, 1.567]
集合第2次随机排序[1.567, asd, null, z, true, 1]
集合第3次随机排序[null, 1, asd, true, 1.567, z]
----------------------------------
集合从小到大排序:[1, 1.567, asd, null, true, z]
----------------------------------
集合从大到小排序排序:[z, true, null, asd, 1.567, 1]
----------------------------------
将集合小标为0和小标为1位置的元素交换:[true, z, null, asd, 1.567, 1]
----------------------------------
对集合进行拷贝:[true, z, null, asd, 1.567, 1]
----------------------------------
将集合中所有1替换为100:true
[true, z, null, asd, 1.567, 100]
*/
操作Collection的常用方法:
@Test
public void test(){
HashSet set = new HashSet();
set.add("1");
set.add("s");
set.add("true");
set.add("1.2");
set.add("null");
set.add("a");
System.out.println(set);
System.out.println("集合中的最大值:" + Collections.max(set, null));
System.out.println("----------------------------------");
System.out.println("集合中的最小值:" + Collections.min(set, null));
System.out.println("----------------------------------");
System.out.println("集合中true出现的次数:" + Collections.frequency(set, "true"));
}
/*
[1, a, s, null, 1.2, true]
集合中的最大值:true
----------------------------------
集合中的最小值:1
----------------------------------
集合中true出现的次数:1
*/
六、日期类
1.Date(第一代日期类)
Date date = new Date();
System.out.println(date); //输出当前时间
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(format.format(date)); //格式化
format = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
Date parse = format.parse("2012年5月18日 8时14分00秒"); //提取时间
//Date parse = format.parse("2012年5月18日 8时14分"); //格式不对,抛出异常
System.out.println(parse);
/*
Wed May 18 10:33:15 CST 2022
2022-05-18 10:33:15
Fri May 18 08:14:00 CST 2012
*/
2.Calendar(第二代日期类)
Calendar calendar = Calendar.getInstance();
System.out.println(calendar);
System.out.println("年:" + calendar.get(Calendar.YEAR));
System.out.println("月:" + (calendar.get(Calendar.MONTH) + 1)); //月份从0开始
System.out.println("日:" + calendar.get(Calendar.DAY_OF_MONTH));
System.out.println("时:" + calendar.get(Calendar.HOUR));
System.out.println("时:" + calendar.get(Calendar.HOUR_OF_DAY)); //24小时制
System.out.println("分:" + calendar.get(Calendar.MINUTE));
System.out.println("秒:" + calendar.get(Calendar.SECOND));
/*
java.util.GregorianCalendar[time=1652841278787,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=29,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2022,MONTH=4,WEEK_OF_YEAR=21,WEEK_OF_MONTH=3,DAY_OF_MONTH=18,DAY_OF_YEAR=138,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=3,AM_PM=0,HOUR=10,HOUR_OF_DAY=10,MINUTE=34,SECOND=38,MILLISECOND=787,ZONE_OFFSET=28800000,DST_OFFSET=0]
年:2022
月:5
日:18
时:10
时:10
分:34
秒:38
*/
3.LocalDateTime(第三代日期类)
LocalDateTime localDataTime = LocalDateTime.now(); //LocalDateTime用于获取年月日时分秒
System.out.println(localDataTime);
System.out.println("年:" + localDataTime.getYear());
//System.out.println(localDataTime.getMonth()); //月份对应的英文
System.out.println("月:" + localDataTime.getMonthValue()); //月份对应的数字
System.out.println("日:" + localDataTime.getDayOfMonth());
System.out.println("时:" + localDataTime.getHour());
System.out.println("分:" + localDataTime.getMinute());
System.out.println("秒:" + localDataTime.getSecond());
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
System.out.println("格式化:" + pattern.format(localDataTime));
//按照东8区(上海)转换成时间戳
Instant instant = localDataTime.toInstant(ZoneOffset.of("+8"));
//然后转换为Date对象
Date date = Date.from(instant);
System.out.println(date);
LocalDateTime nextMonth = localDataTime.plusMonths(1);
System.out.println("一个月后的时间:" + pattern.format(nextMonth));
LocalDateTime nextWeek = localDataTime.plusWeeks(1);
System.out.println("一周后的时间:" + pattern.format(nextWeek));
System.out.println("--------------------------------------------");
LocalDate localDate = LocalDate.now(); //LocalDate用于获取年月日
System.out.println("年:" + localDate.getYear());
System.out.println("月:" + localDate.getMonthValue());
System.out.println("日:" + localDate.getDayOfMonth());
System.out.println("今年是否为闰年:" + localDate.isLeapYear());
pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
System.out.println("格式化:" + pattern.format(localDate));
System.out.println("--------------------------------------------");
LocalTime localTime = LocalTime.now(); //LocalTime用于获取时分秒
System.out.println("时:" + localTime.getHour());
System.out.println("分:" + localTime.getMinute());
System.out.println("秒:" + localTime.getSecond());
pattern = DateTimeFormatter.ofPattern("HH时mm分ss秒");
System.out.println("格式化:" + pattern.format(localTime));
/*
2022-05-18T10:35:21.205
年:2022
月:5
日:18
时:10
分:35
秒:21
格式化:2022年05月18日 10时35分21秒
Wed May 18 10:35:21 CST 2022
一个月后的时间:2022年06月18日 10时35分21秒
一个月后的时间:2022年05月25日 10时35分21秒
--------------------------------------------
年:2022
月:5
日:18
今年是否为闰年:false
格式化:2022年05月18日
--------------------------------------------
时:10
分:35
秒:21
格式化:10时35分21秒
*/
Date类在引入Calendar类之后大多数方法被弃用了。
Calendar存在问题:
-
可变性:像日期和时间这样的类应该是不可变的。
-
偏移性:Date中的年份是从1900开始的,而月份都从0开始。
-
格式化:格式化只对Date有用,Calendar则不行。
-
线程不安全的,不能处理闰秒等(每隔2天,多出1s)。
推荐使用第三代日期类