字符串相关类
String类
String的特性
- String:字符串,使用一对””引起来表示。
- String声明为
final
的,不可被继承。 - String实现了
Serializable
接口:表示字符串是支持序列化的。实现了Comparable
接口:表示String可以比较大小。 - String内部定义了
final char[] value
用于存储字符串数据。 String:代表不可变的字符序列。简称:不可变性。
通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
- 字符串常量池中是不会存储相同内容的字符串的。
//通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。
//s1和s2的地址值是相同的。
String s1 = "javaEE";
String s2 = "javaEE";
方式二:new + 构造器
//本质上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);
//通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false
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"
String str1 = “abc”;
与String str2 = new String(“abc”);
的区别?- 字符串常量存储在字符串常量池,目的是共享。
- 字符串非常量对象存储在堆中。
- 判断
int length()
:返回字符串的长度: return value.lengthchar charAt(int index)
: 返回某索引处的字符:return value[index]boolean isEmpty()
:判断是否是空字符串:return value.length == 0String toLowerCase()
:将 String 中的所有字符转换为小写。String toUpperCase()
:将 String 中的所有字符转换为大写。- 🌟
String trim()
:返回字符串的副本,忽略前导空白和尾部空白。 boolean equals(Object obj)
:比较字符串的内容是否相同。boolean equalsIgnoreCase(String anotherString)
:与equals方法类似,忽略大小写。String concat(String str)
:将指定字符串连接到此字符串的结尾。 等价于用“+”。int compareTo(String anotherString)
:比较两个字符串的大小。String substring(int beginIndex)
:返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
String substring(int beginIndex, int endIndex)
:返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串(左闭右开)。
boolean endsWith(String suffix)
:测试此字符串是否以指定的后缀结束。boolean startsWith(String prefix)
:测试此字符串是否以指定的前缀开始。boolean startsWith(String prefix, int toffset)
:测试此字符串从指定索引开始的子字符串是否以指定前缀开始。boolean contains(CharSequence s)
:当且仅当此字符串包含指定的 char 值序列时,返回 true。int indexOf(String str)
:返回指定子字符串在此字符串中第一次出现处的索引。int indexOf(String str, int fromIndex)
:返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始int lastIndexOf(String str)
:返回指定子字符串在此字符串中最右边出现处的索引。int lastIndexOf(String str, int fromIndex)
:返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
注:indexOf
和lastIndexOf
方法如果未找到都是返回-1。替换:
String replace(char oldChar, char newChar)
:返回一个新的字符串,它是通过用新字符替换此字符串中出现的所有旧字符得到的。String replace(CharSequence target, CharSequence replacement)
:使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。String replaceAll(String regex, String replacement)
:使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。String replaceFirst(String regex, String replacement)
:使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。匹配:
boolean matches(String regex)
:告知此字符串是否匹配给定的正则表达式。切片:
String[] split(String regex)
:根据给定正则表达式的匹配拆分此字符串。String[] split(String regex, int limit)
:根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。String转换
- String 与 char[]之间的转换。
String --> char[]:调用String的toCharArray()
char[] --> String:调用String的构造器
String str1 = "abc123";
char[] charArray = str1.toCharArray();
for (int i = 0; i < charArray.length; i++) {
System.out.println(charArray[i]);
}
char[] arr = new char[]{'h','e','l','l','o'};
String str2 = new String(arr);
System.out.println(str2);
- 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字符集进行编码。
System.out.println(Arrays.toString(gbks));
System.out.println("******************");
String str2 = new String(bytes);//使用默认的字符集,进行解码。
System.out.println(str2);
String str3 = new String(gbks);
System.out.println(str3);//出现乱码。原因:编码集和解码集不一致!
String str4 = new String(gbks, "gbk");
System.out.println(str4);//没有出现乱码。原因:编码集和解码集一致!
}
说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。
StringBuffer和StringBuilder类
String、StringBuffer、StringBuilder三者的异同?
String
:不可变的字符序列;底层使用char[]存储。StringBuffer
:可变的字符序列;线程安全的,效率低;底层使用char[]存储。StringBuilder
:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储。
效率从高到低排列:StringBuilder > StringBuffer > String
源码分析:
String str = new String();//char[] value = new char[0];
String str1 = new String("abc");//char[] value = new char[]{'a','b','c'};
StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度是16的数组。
System.out.println(sb1.length());//
sb1.append('a');//value[0] = 'a';
sb1.append('b');//value[1] = 'b';
StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length() + 16];
问题1. System.out.println(sb2.length());//3
问题2. 扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组。
默认情况下,扩容为原来容量的2倍 + 2,同时将原有数组中的元素复制到新的数组中。
指导意义:开发中建议大家使用:StringBuffer(int capacity) 或 StringBuilder(int capacity),尽量减少扩容提高效率。
StringBuffer常用方法
StringBuffer append(xxx)
:提供了很多的append()方法,用于进行字符串拼接。StringBuffer delete(int start,int end)
:删除指定位置的内容。StringBuffer replace(int start, int end, String str)
:把[start,end)位置替换为str。StringBuffer insert(int offset, xxx)
:在指定位置插入xxx。StringBuffer reverse()
:把当前字符序列逆转。public int indexOf(String str)
:返回指定子字符串在此字符串中第一次出现处的索引。public String substring(int start,int end)
:返回一个从start开始到end索引结束的左闭右开区间的子字符串。public int length()
public char charAt(int n )
public void setCharAt(int n ,char ch)
总结:
增:append(xxx)
删:delete(int start,int end)
改:setCharAt(int n ,char ch) / replace(int start, int end, String str)
查:charAt(int n)
插:insert(int offset, xxx)
长度:length()
遍历:for() + charAt() / toString()
日期时间api
java.lang.System类
返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差,称为时间戳。long time = System.currentTimeMillis();
java.util.Date类
- 两个构造器的使用
>构造器一:Date()
:创建一个对应当前时间的Date对象。
>构造器二:创建指定毫秒数的Date对象 ```java //构造器一:Date():创建一个对应当前时间的Date对象 Date date1 = new Date(); System.out.println(date1.toString());//Sat Feb 16 16:35:31 GMT+08:00 2019
System.out.println(date1.getTime());//1550306204104
//构造器二:创建指定毫秒数的Date对象 Date date2 = new Date(155030620410L); System.out.println(date2.toString());
2. 两个方法的使用<br /> >`toString()`:显示当前的年、月、日、时、分、秒。<br /> >`getTime()`:获取当前Date对象对应的毫秒数。(时间戳)
<a name="pNlWT"></a>
### java.sql.Date类(子类)
对应着数据库中的日期类型的变量
1. 如何实例化
```java
//创建java.sql.Date对象
java.sql.Date date3 = new java.sql.Date(35235325345L);
System.out.println(date3);//1971-02-13
- 如何将java.util.Date对象转换为java.sql.Date对象 ```java //情况一: Date date4 = new java.sql.Date(2343243242323L); java.sql.Date date5 = (java.sql.Date) date4;
//情况二: Date date6 = new Date(); java.sql.Date date7 = new java.sql.Date(date6.getTime());
<a name="HNNdM"></a>
## SimpleDateFormat类
`Date类`的API不易于国际化,大部分被废弃了,`java.text.SimpleDateFormat 类`是一个不与语言环境有关的方式来**格式化和解析日期的具体类**。
1. 两个操作:
- 格式化:日期 --->字符串
```java
//格式化:日期 --->字符串
Date date = new Date();
System.out.println(date);
String format = sdf.format(date);
System.out.println(format);
- 解析:格式化的逆过程,字符串 —-> 日期
//解析:格式化的逆过程,字符串 ---> 日期 String str = "19-12-18 上午11:43"; Date date1 = sdf.parse(str); System.out.println(date1);
SimpleDateFormat的实例化
//实例化SimpleDateFormat:使用默认的构造器 SimpleDateFormat sdf = new SimpleDateFormat();
按照指定的方式格式化和解析:调用带参的构造器。�
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //格式化 String format1 = sdf1.format(date); System.out.println(format1);//2019-02-18 11:48:27 //解析:要求字符串必须是符合SimpleDateFormat识别的格式(通过构造器参数体现), //否则,抛异常 Date date2 = sdf1.parse("2020-02-18 11:48:27"); System.out.println(date2);
java.util.Calendar类
Calendar
是一个抽象基类,主用用于完成日期字段之间相互操作的功能。
获取月份时:一月是0,二月是1,以此类推,12月是11。
获取星期时:周日是1,周二是2 , ……周六是7。实例化
//方式一:创建其子类(GregorianCalendar)的对象 //方式二:调用其静态方法getInstance() Calendar calendar = Calendar.getInstance(); // System.out.println(calendar.getClass());
常用方法
get()
YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY 、 MINUTE、SECOND。
int days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
set()
calendar可变性。
calendar.set(Calendar.DAY_OF_MONTH,22);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
add()
calendar.add(Calendar.DAY_OF_MONTH,-3); days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days);
getTime()
:日历类—-> DateDate date = calendar.getTime(); System.out.println(date);
setTime()
:Date —-> 日历类Date date1 = new Date(); calendar.setTime(date1); days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days);
JDK8中新日期时间API
LocalDate、LocalTime、LocalDateTime类
LocalDate
、LocalTime
、LocalDateTime
类是其中较重要的几个类,它们的实例 是不可变的对象。LocalDateTime
相较于LocalDate
、LocalTime
,使用频率要高,类似于Calendar
。
�LocalDate
代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。LocalTime
表示一个时间,而不是日期。LocalDateTime
是用来表示日期和时间的,这是一个最常用的类之一。
相关方法:
now()
:获取当前的日期、时间、日期+时间。 ```java LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDate); System.out.println(localTime); System.out.println(localDateTime);
2. `of()`:设置指定的年、月、日、时、分、秒(没有偏移量)。
```java
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23, 43);
System.out.println(localDateTime1);
getXxx()
:获取相关的属性。System.out.println(localDateTime.getDayOfMonth()); System.out.println(localDateTime.getDayOfWeek()); System.out.println(localDateTime.getMonth()); System.out.println(localDateTime.getMonthValue()); System.out.println(localDateTime.getMinute());
withXxx()
:设置相关的属性(体现不可变性)。 ```java LocalDate localDate1 = localDate.withDayOfMonth(22); System.out.println(localDate); System.out.println(localDate1);
LocalDateTime localDateTime2 = localDateTime.withHour(4); System.out.println(localDateTime); System.out.println(localDateTime2);
5. `plusXxx()/minusXxx()`:加/减几年、月、日(体现不可变性)。
```java
LocalDateTime localDateTime3 = localDateTime.plusMonths(3);
System.out.println(localDateTime);
System.out.println(localDateTime3);
LocalDateTime localDateTime4 = localDateTime.minusDays(6);
System.out.println(localDateTime);
System.out.println(localDateTime4);
瞬时:Instant
时间线上的一个瞬时点。这可能被用来记录应用程序中的事件时间戳。从1970年开始,但以毫秒为单位。类似于 java.util.Date类。
now()
:获取本初子午线对应的标准时间。Instant instant = Instant.now(); System.out.println(instant);//2019-02-18T07:29:41.719Z
atOffset()
:添加时间的偏移量。OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8)); System.out.println(offsetDateTime);//2019-02-18T15:32:50.611+08:00
toEpochMilli()
:获取自1970年1月1日0时0分0秒(UTC)开始的毫秒数 —-> Date类的getTime()。long milli = instant.toEpochMilli(); System.out.println(milli);
ofEpochMilli()
:通过给定的毫秒数,获取Instant实例 —>Date(long millis)。Instant instant1 = Instant.ofEpochMilli(1550475314878L); System.out.println(instant1);
DateTimeFormatter类
格式化或解析日期、时间,类似于
SimpleDateFormat
。
- �方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME。 ```java DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; //格式化:日期—>字符串 LocalDateTime localDateTime = LocalDateTime.now(); String str1 = formatter.format(localDateTime); System.out.println(localDateTime); System.out.println(str1);//2019-02-18T15:42:18.797
//解析:字符串 —>日期 TemporalAccessor parse = formatter.parse(“2019-02-18T15:42:18.797”); System.out.println(parse);
- 方式二:本地化相关的格式。
```java
// 本地化相关的格式。如:ofLocalizedDateTime()
// FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT :适用于LocalDateTime
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
//格式化
String str2 = formatter1.format(localDateTime);
System.out.println(str2);//2019年2月18日 下午03时47分16秒
// 本地化相关的格式。如:ofLocalizedDate()
// FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT : 适用于LocalDate
DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
//格式化
String str3 = formatter2.format(LocalDate.now());
System.out.println(str3);//2019-2-18
- 方式三:自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)。 ```java DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern(“yyyy-MM-dd hh:mm:ss”); //格式化 String str4 = formatter3.format(LocalDateTime.now()); System.out.println(str4);//2019-02-18 03:52:09
//解析 TemporalAccessor accessor = formatter3.parse(“2019-02-18 03:52:09”); System.out.println(accessor);
---
<a name="EcXvw"></a>
# Java比较器
Java中的对象,正常情况下,只能进行比较:== 或 != ,不能使用 > 或 < 。<br />但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。<br />如何实现?使用两个接口中的任何一个:`Comparable` 或 `Comparator`。
<a name="v4Vq3"></a>
## Comparable接口(自然排序)
1. 像**String、包装类**等实现了Comparable接口,重写了`compareTo(obj)`方法,给出了比较两个对象大小的方式。
1. 重写`compareTo(obj)`的规则:
- 如果当前对象this大于形参对象obj,则返回正整数。
- 如果当前对象this小于形参对象obj,则返回负整数。
- 如果当前对象this等于形参对象obj,则返回零。
3. 对于**自定义类**来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写`compareTo(obj)`方法,在`compareTo(obj)`方法中指明如何排序。
```java
//指明商品比较大小的方式:按照价格从低到高排序,再按照产品名称从高到低排序
@Override
public int compareTo(Object o) {
// System.out.println("**************");
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;
return -this.name.compareTo(goods.name);
}
//方式二:
// return Double.compare(this.price,goods.price);
}
// return 0;
throw new RuntimeException("传入的数据类型不一致!");
}
@Test
public void test1() {
Goods[] goods = new Goods[4];
goods[0] = new Goods("Apple", 5000);
goods[1] = new Goods("HuaWei", 6000);
goods[2] = new Goods("Xiaomi", 9000);
goods[3] = new Goods("Vivo", 8000);
Arrays.sort(goods);
System.out.println(Arrays.toString(goods));
}
Comparator接口(定制排序)
- 背景:
当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序。 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
- 如果方法返回正整数,则表示o1大于o2;
- 如果返回0,表示相等;
返回负整数,表示o1小于o2。
String[] arr = new String[]{"AA","CC","KK","MM","GG","JJ","DD"}; 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); } // return 0; throw new RuntimeException("输入的数据类型不一致"); } }); System.out.println(Arrays.toString(arr));
```java Goods[] arr = new Goods[6]; arr[0] = new Goods(“lenovoMouse”,34); arr[1] = new Goods(“dellMouse”,43); arr[2] = new Goods(“xiaomiMouse”,12); arr[3] = new Goods(“huaweiMouse”,65); arr[4] = new Goods(“huaweiMouse”,224); arr[5] = new Goods(“microsoftMouse”,43);
Arrays.sort(arr, new Comparator() { //指明商品比较大小的方式:按照产品名称从低到高排序,再按照价格从高到低排序 @Override public int compare(Object o1, Object o2) { if(o1 instanceof Goods && o2 instanceof Goods){ Goods g1 = (Goods)o1; Goods g2 = (Goods)o2; if(g1.getName().equals(g2.getName())){ return -Double.compare(g1.getPrice(),g2.getPrice()); }else{ return g1.getName().compareTo(g2.getName()); } } throw new RuntimeException(“输入的数据类型不一致”); } });
System.out.println(Arrays.toString(arr));
---
<a name="MLxs4"></a>
# System类
- `native long currentTimeMillis()`: 该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时 间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
- `void exit(int status)`: 该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表 异常退出。使用该方法可以在图形界面编程中实现程序的退出功能等。
- `void gc()`: 该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
- `String getProperty(String key)`: 该方法的作用是获得系统中属性名为key的属性对应的值。系统中常见 的属性名以及属性的作用如下表所示:

```java
@Test
public void test1() {
String javaVersion = System.getProperty("java.version");
System.out.println("java的version:" + javaVersion);
String javaHome = System.getProperty("java.home");
System.out.println("java的home:" + javaHome);
String osName = System.getProperty("os.name");
System.out.println("os的name:" + osName);
String osVersion = System.getProperty("os.version");
System.out.println("os的version:" + osVersion);
String userName = System.getProperty("user.name");
System.out.println("user的name:" + userName);
String userHome = System.getProperty("user.home");
System.out.println("user的home:" + userHome);
String userDir = System.getProperty("user.dir");
System.out.println("user的dir:" + userDir);
}
Math类
java.lang.Math
提供了一系列静态方法用于科学计算。其方法的参数和返回 值类型一般为double型。
abs
绝对值acos,asin,atan,cos,sin,tan
三角函数sqrt
平方根pow(double a,doble b)
a的b次幂log
自然对数exp
e为底指数max(double a,double b)
min(double a,double b)
random()
返回0.0到1.0的随机数long round(double a)
double型数据a转换为long型(四舍五入)toDegrees(double angrad)
弧度—>角度toRadians(double angdeg)
角度—>弧度
BigInteger与BigDecimal类
BigInteger类
可以表示不可变的任意精度的整数。BigDecimal类
支持不可变的、任意精度的有符号十进制定点数。
BigInteger bi = new BigInteger("1243324112234324324325235245346567657653");
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bi);
// System.out.println(bd.divide(bd2));
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2, 25, BigDecimal.ROUND_HALF_UP));
�