常用类
常用类
- 字符串相关的类
- String类及常用方法
- StringBuffer
- StringBuilder
- JDK8之前的日期时间API
- System静态方法---------->currentTimeMillis()
- Date类
- Calendar类
- SimpleDateFormat类
- JDK8中新日期时间API
- LocalDate
- LocalTime
- LocalDateTime
- Instant
- DateTimeFormatter
- Java比较器
- Compara接口
- Comparator接口
- System类
- Math类
- BigInteger与BigDecimal
String
-
String类:代表字符串
-
String实现了Serializable接口:表示字符串是支持序列化的。
实现了Comparable接口:表示String可以比较大小。 -
String内部定义了final char[] value用于存储字符串数据。
-
String:代表不可变的字符序列。简称:不可变性。
-
体现:
- 当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
- 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value赋值。
- 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值。
-
@Test public void test1(){ String s1="abc";//字面量 String s2="abc"; s1="hello"; System.out.println(s1);//hello System.out.println(s2);//abc
-
-
字符串是常量,它们的值在创建之后不能更改。
-
String对象的字符内容是存储在一个字符数组value[]中的。
-
通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
-
字符串常量池中是不会存储相同内容的字符串。
String对象的创建
String的实例化方式:
-
通过字面量定义的方式
-
通过new + 构造器的方式
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);
@Test
public void test2(){
//通过字面量定义的方法:此时的s1和s2的数据javaEE声明在方法区的字符串常量池中。
String s1 = "javaEE";
String s2 = "javaEE";
//通过new+构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1==s2);//true
System.out.println(s2==s3);//false
System.out.println(s3==s4);//false
System.out.println(s4==s1);//false
System.out.println("=================");
Person p1 = new Person("Tom",12);
Person p2 = new Person("Tom",12);
System.out.println(p1.name.equals(p2.name));//true
System.out.println(p1.name==p2.name);//true
p1.name = "Jerry";
System.out.println(p2.name);//Tom
}
图解:
面试题:
- String s = new String("abc");方式创建对象,在内存中创建了几个对象?
- 两个:一个是在堆空间中new结构,另一个是char[]对应的常量池中的数据:"abc"。
@Test
public void test3(){
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE"+"hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE"+s2;
String s7 = s1+s2;
String s8 = s5.intern();//返回值得到的s8使用的常量值中已经存在的“javaEEhadoop”
System.out.println(s3==s4);//true
System.out.println(s3==s5);//false
System.out.println(s3==s6);//false
System.out.println(s3==s7);//false
System.out.println(s5==s6);//false
System.out.println(s5==s7);//false
System.out.println(s6==s7);//false
System.out.println(s3==s8);//true
}
结论:
- 常量与常量的拼接结果在常量池,且常量池中不会存在相同内容的常量。
- 只要其中有一个变量,结果就在堆中。
- 如果拼接的结果调用intern()方法,返回值就在常量池中。
面试题:
public class StringTest {
String str = new String("good");
char[] ch ={'t','e','s','t'};
public void change(String str,char ch[]){
str = "test ok";
ch[0] = 'b';
}
public static void main(String[] args) {
StringTest ex = new StringTest();
ex.change(ex.str, ex.ch);
System.out.println(ex.str);//good
System.out.println(ex.ch);//best
}
}
String类常用方法
package stringtest;
import org.junit.jupiter.api.Test;
public class StringMethodTest {
@Test
public void test(){
String s1 = "Hello World";
String s2 = new String(" boom shit ");
String s3 = "Hello World";
String s4 = new String("Hello World");
String s5 = new String("Hello Worlda");
String s6 = "d";
System.out.println(s1.length());//11
System.out.println(s1.charAt(8));//r
System.out.println(s1.isEmpty());//false
System.out.println(s1.toLowerCase());//hello world
System.out.println(s1.toUpperCase());//HELLO WORLD
System.out.println(s2.trim());//boom shit
System.out.println(s1.equals(s3));//true
System.out.println(s1.equals(s4));//true
System.out.println(s1.equalsIgnoreCase(s3.toUpperCase()));//true
System.out.println(s1.concat(s3));//Hello WorldHello World
System.out.println(s1.compareTo(s5));//-1
System.out.println(s1.substring(3));//lo World
System.out.println(s1.substring(3,7));//lo W
System.out.println(s1.endsWith(s6));//true
System.out.println(s1.endsWith(s3));//true
System.out.println(s1.startsWith(s3));//true
System.out.println(s1.startsWith("he",0));//false
String s7 = "hello world";
String s8 = new String("hello");
System.out.println(s7.contains(s8));//true
System.out.println(s7.indexOf("lo"));//3
System.out.println(s7.indexOf("l",3));//3
System.out.println(s7.indexOf("es"));//-1
String s9 = new String("abbccddccbba");
//索引从左边开始计数,而不是按搜索顺序计数
System.out.println(s9.lastIndexOf("bb"));//9
System.out.println(s9.lastIndexOf("bb",6));//1
System.out.println(s9.lastIndexOf("ee"));//-1
String t1 = "Hello World";
String t2 = new String("boom shit");
String t4 = "ff";
String t3 = t1.replace("Hello", t2);
String t5 = t1.replace(t1, t4);
System.out.println(t3);//boom shit World
System.out.println(t5);//ff
String t6 = "大大得到的道德";
String t7 = t6.replace('大', '小');
String t8 = t6.replace("道德", "答复");
System.out.println(t7);//小小得到的道德
System.out.println(t8);//大大得到的答复
String str1 = "12hello23world13java2322mysql2323";
String str2 = str1.replaceAll("\\d+", ",");
System.out.println(str2);//,hello,world,java,mysql,
String str3 = str2.replaceAll("^,|,$", "");
System.out.println(str3);//hello,world,java,mysql\
String str5 = new String("12345");
boolean matches = str5.matches("\\d+");
System.out.println(matches);//true
}
}
String与基本数据类型、包装类之间的转换
-
String-->基本数据类型、包装类:
-
调用包装类的静态方法:parseXxx(str)
-
基本数据类型、包装类-->String:
- 调用String重载的valueOf(xxx)
@Test
public void test1(){
String str1 = "123";
// int num = (int)str1;//错误
int i = Integer.parseInt(str1);
System.out.println(i);
i++;
String str2 = String.valueOf(i);
String str3 = i +"";
System.out.println(str1==str3);//false
}
String与char[]之间的转换
-
String-->char[]:
- 调用String的tocharArray();
-
char[] -->String :
- 调用String的构造器
@Test
public void test2(){
String str1 = "abc123";
char[] charArray = str1.toCharArray();
for (char i :charArray) {
System.out.println(i);
}
char[] arr =new char[]{'h', 'e', 'l', 'l', 'o'};
String str2 = new String(arr);
System.out.println(str2);//hello
}
String与byte[]之间的转换
编码:String-->byte[]:调用String的getBytes()
解码:byte[]-->String:调用String的构造器
编码:字符串-->字节
解码:字节-->字符串
解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。
@Test
public void test3() throws UnsupportedEncodingException {
String str1 = "abc123中国";
byte[] bytes = str1.getBytes();//使用默认的字符集,进行编码
System.out.println(Arrays.toString(bytes));
byte[] gbks = str1.getBytes("gbk");//使用gbk字符集进行编码
// for (byte i:gbks) {
// System.out.print(i+" ");
// }
System.out.println(Arrays.toString(gbks));
System.out.println();
String str2 = new String(bytes);//使用默认字符集进行解码
System.out.println(str2);//abc123中国
String str3 = new String(gbks);
System.out.println(str3);//出现乱码。原因;编码集和解码集不一致
String gbk = new String(gbks, "gbk");
System.out.println(gbk);//abc123中国
}
String、StringBuffer和StringBuilder三者的异同
String:不可变的字符序列:底层用final char[]存储
StringBuffer:可变的字符序列,线程安全的,效率低,底层用char[]存储
StringBuilder:可变的字符序列,线程不安全的,效率高,底层用char[]存储
String、StringBuffer和StringBuilder三者相互转换
调用转换类的构造器就行
源码分析:
@Test
public void test1(){
StringBuffer sb1 = new StringBuffer("abc");
sb1.setCharAt(1,'k');
System.out.println(sb1);//akc
String str = new String();//final char[] value = new char[0];
String str1 = new String("abc");//final char[] value = new char[]{'a','b','c'};
StringBuffer sb2 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度为16的数组
System.out.println(sb2.length());//0
sb2.append('a');//value[0] = 'a';
sb2.append('b');//value[1] = 'b';
sb2.append('c');//value[2] = 'c';
System.out.println(sb2);//abc
System.out.println(sb2.length());//3
StringBuffer sb3 = new StringBuffer("abcd");//char[] value = new char["abc".length()+16];
/**
* 扩容问题:
* 默认情况下,扩容为原来容量的2倍+2,同时将原来数组中的元素复制到新的数组中去
* 指导意义:建议使用:StringBuffer(int capacity)或StringBuilder(int capacity)
*/
StringBuffer类常用方法
以上方法支持方法链原理,原理如下
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
遍历需要for循环
for (int i = 0;i<stringbuffer.length();i++) {
System.out.println(stringbuffer.charAt(i));
}
@Test
public void test1(){
StringBuffer sb1 = new StringBuffer("abc");
char[] ch = {'a','c'};
sb1.append(1).append(ch);
System.out.println(sb1);//abc1ac
sb1.delete(1,4);
System.out.println(sb1);//aac
String str1 = new String("lll");
sb1.replace(1,2,str1);
System.out.println(sb1);//alllc
sb1.insert(0,123);
System.out.println(sb1);//123alllc
sb1.reverse();
System.out.println(sb1);//cllla321
sb1.setCharAt(3,'A');
System.out.println(sb1);//cllAa321
System.out.println(sb1.substring(1,3));//ll
}
JDK8之前的日期时间API
java.lang.System类
System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日之间以毫秒为单位的时间差。
@Test
public void test1(){
System.out.println(currentTimeMillis());
}
可用于订单编号
java.util.Date类
Date类的两个构造器的使用:
- Date():创建一个对应当前时间的Date对象
- Date(long)创建指定毫秒数的Date对象
java.util.Date类常用方法
@Test
public void test1(){
Date date1 = new Date();
System.out.println(date1.toString());//Sat Dec 05 00:43:41 CST 2020
System.out.println(date1.getTime());//1607100221127
Date date2 = new Date(1606997024829L);
System.out.println(date2.toString());//Thu Dec 03 20:03:44 CST 2020
}
创建java.sql.Date对象
java.sql.Date date3 = new java.sql.Date(1607100221127L);
System.out.println(date3);//2020-12-05
如何将java.util.Date对象转换为java.sql.Date对象
//方法一:
Date date4 = new java.sql.Date(1607100422833L);
java.sql.Date date5 = (java.sql.Date) date4;
System.out.println(date5);//2020-12-05
//方法二:
Date date6 = new Date();
java.sql.Date date7 = new java.sql.Date(date6.getTime());
System.out.println(date7);//2020-12-05
SimpleDateFormat类
该类是一个不与语言环境有关的方式来格式化和解析日期的具体类
它允许进行格式化:日期-->文本
解析:文本-->日期
@Test
public void test1() throws ParseException {
//实例化SimpleDateFormat:使用默认的构造器
SimpleDateFormat sdf = new SimpleDateFormat();
Date date = new Date();
System.out.println(date);//Sat Dec 05 01:52:35 CST 2020
//格式化:日期-->字符串
String format = sdf.format(date);
System.out.println(format);//20-12-5 上午1:52
//解析:字符串-->日期
String str = "20-12-34 下午3:32";
Date date1 = sdf.parse(str);
System.out.println(date1);//Sun Jan 03 15:32:00 CST 2021
//调用有参构造器
// SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//按照指定方式解析
//格式化
String format1 = sdf2.format(date);
System.out.println(format1);//2020-12-05 02:06:37
//解析 要求解析的字符串必须符合SimpleDateFormat格式(通过SimpleDateFormat构造器有参参数体现)
Date date2 = sdf2.parse("2020-12-05 02:06:37");
System.out.println(date2);//Sat Dec 05 02:06:37 CST 2020
}
练习一:字符串"2020-09-08"转换为java.sql.Date
@Test
public void test1() throws ParseException {
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = sdf1.parse("2020-09-08");
System.out.println(date1);
java.sql.Date date2 = new java.sql.Date(date1.getTime());
System.out.println(date2);
}
练习二:从1990-01-01开始“三天打渔两天晒网“,2020-09-08是打渔还是晒网?
@Test
public void test2() throws ParseException {
//1990-01-01 2020-09-08
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = simpleDateFormat.parse("1990-01-01");
long time1 = date1.getTime();
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
Date date2 = simpleDateFormat1.parse("2020-09-08");
long time2 = date2.getTime();
long timeSub = time2 - time1;
long i = 86_400_000L;//一天的毫秒数
long day = timeSub / i ;
int j = (int)day%5;
switch (j){
case 0:
System.out.println("晒网");
break;
case 1:
System.out.println("打渔");
break;
case 2:
System.out.println("打渔");
break;
case 3:
System.out.println("打渔");
break;
case 4:
System.out.println("晒网");
break;
}
}
Calendar类(抽象类)
实例化方法:
- 创建其子类GregorianCalendar的对象
- 调用其静态方法getInstance()
@Test
public void test1(){
Calendar calendar = Calendar.getInstance();
//get()
int days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
//set()
calendar.set(Calendar.DAY_OF_YEAR,13);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
//add()
calendar.add(Calendar.DAY_OF_YEAR,33);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
//getTime() 日历类-->Date
Date date = calendar.getTime();
System.out.println(date);
//setTime() Date-->日历类
Date date1 = new Date();
calendar.setTime(date1);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
}
Calendar的常用方法:
LocalDate、LocalTime、LocalDateTime
常用方法:
@Test
public void test(){
//实例化方式:now(),of()
//now()
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
/*
2020-12-05
14:53:33.926
2020-12-05T14:53:33.926
*/
System.out.println(localDate);
System.out.println(localTime);
System.out.println(localDateTime);
//of() 设置指定的年,月,日,时,分,秒,没有偏移量
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 12, 22, 15, 22,33);
System.out.println(localDateTime1);//2020-12-22T15:22:33
System.out.println("==================================");
//getXxx()
System.out.println(localDateTime1.getDayOfMonth());//22
System.out.println(localDateTime1.getDayOfYear());//357
System.out.println(localDateTime1.getDayOfWeek());//TUESDAY
System.out.println(localDateTime1.getMonth());//DECEMBER
System.out.println(localDateTime1.getMonthValue());//12
System.out.println(localDateTime1.getMinute());//22
System.out.println(localDateTime1.getSecond());//33
//体现不可变性
//withXxx():设置相关属性
LocalDateTime localDateTime2 = localDateTime1.withDayOfMonth(22);
System.out.println(localDateTime1);//2020-12-30T15:22:33
System.out.println(localDateTime2);//2020-12-22T15:22:33
LocalDateTime time3 = localDateTime1.plusDays(2);
System.out.println(time3);//2020-12-24T15:22:33
LocalDateTime time4 = localDateTime1.minusHours(3);
System.out.println(time4);//2020-12-22T12:22:33
}
Instant类
常用方法
@Test
public void test1(){
Instant now = Instant.now();
System.out.println(now);//返回的时间时本初子母线的时间
}
DateTimeFormatter类
格式化或解析日期、时间
@Test
public void test3(){
DateTimeFormatter time3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
//格式化
String s = time3.format(LocalDateTime.now());
System.out.println(s);//2020-12-05 03:36:08
//解析
TemporalAccessor accessor = time3.parse("2020-12-30 05:22:33");
System.out.println(accessor);//{NanoOfSecond=0, SecondOfMinute=33, MicroOfSecond=0, MilliOfSecond=0, MinuteOfHour=22, HourOfAmPm=5},ISO resolved to 2020-12-30
}
Java比较器
使用Comparable接口和Comparator,对对象进行排序.
Comparable接口的使用举例:自然排序
- String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式。
- String、包装类重写compareTo()方法以后,进行了大小排列。
- 重写compareTo(obj)的规则:
- 如果当前对象this大于形参对象obj,则返回正整数,
- 如果当前对象this小于形参对象obj,则返回负整数,
- 如果当前对象this等于于形参对象obj,则返回0。
- 对于自定义类来说,如果需要排序,我们可以让自定义类来实现Comparable接口,重写compareTo(obj)方法.
package compareTest;
public class Goods implements Comparable{
private String name;
private double price;
public Goods() {
}
public Goods(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
//指明排序方式
@Override
public int compareTo(Object o) {
if (o instanceof Goods){
Goods goods = (Goods)o;
if (this.price > goods.price){
return 1;
}else if(this.price<goods.price){
return -1;
}else
return 0;
}
throw new RuntimeException("数据有问题");
}
}
package compareTest;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
public class CompareTest {
@Test
public void test(){
Goods[] arr = new Goods[4];
arr[0] = new Goods("lenovn",5);
arr[1] = new Goods("dell",6);
arr[2] = new Goods("xiaomi",3);
arr[3] = new Goods("huawei",9);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));//[Goods{name='xiaomi', price=3.0}, Goods{name='lenovn', price=5.0}, Goods{name='dell', price=6.0}, Goods{name='huawei', price=9.0}]
}
}
Comparator接口的使用:定制排序
-
背景:
- 当元素的类型没有实现Comparable接口而又不方便修改代码,或者实现了Comparable接口但排序规则不适合当前的操作。
-
重写comparator(object o1,object o2)方法,比较o1和o2的大小:
返回正整数,o1>o2
返回负整数,o1<o2
返回0,o1=o2
@Test
public void test1(){
String[] arr = new String[]{"AA","CC","FF","EE","DD","GG","HH"};
Arrays.sort(arr,new Comparator(){
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof String && o2 instanceof String){
String s1 = (String) o1;
String s2 = (String) o2;
return s1.compareTo(s2);
}
throw new RuntimeException("输入的数据类型不一致");
}
});
System.out.println(Arrays.toString(arr));
}
二者对比
- Comparable接口的方式一旦一定,保证Comparable接口实现类的对象在任何位置都可以比较大小。
- Comparator接口属于临时性的比较。