目录
- 1. String
-
- 1.1 String对象的简介
- 1.2 String的内存结构
- 1.3 字符串的拼接
- 1.4 常用的方法
- 2. StringBuffer和StringBuilder
-
- 2.1 简介:
- 2.2 常用的方法
- 2.3 区别
- 3. 传统日期和时间处理
-
- 3.1 System类
- 3.2 Date
- 3.3 SimpleDateFormat
- 4. Calender
- 5. JDK新日期API
-
- 5.1 LocalDateTime和 Instant
- 5.3 DateTimeFormatter
1. String
1.1 String对象的简介
简介:
- String类:代表字符串,Java程序中的所有字符串字面值(如”abc“)都作为此类的实例实现
- String是一个final类,代表不可变的字符序列
- 字符串是常量,用双引号引起来表示,它们的值在创建之后不能更改
- String对象的字符内容是存放在一个字符数组value[]中的
产生字符串的方式
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);
1.2 String的内存结构
1.3 字符串的拼接
- 常量与常量的拼接结果在常量池中,且常量池中不会出现内容相同发常量
- 只要其中一个是变量,结果就在堆中
- 如果拼接的结果调用intern()方法,返回值就在常量池中
- Strings1 = "a"说明在字符串常量池中创建了一个字面量为”a“的字符串
- s1 = s1 + “b”; 说明:实际上原来的“a”字符串对象已经丢弃了, 现在在堆空间中产生了一个字符串
s1+“b”(也就是"ab")。如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内
存中,降低效率。如果这样的操作放到循环中,会极大影响程序的性能。 - String s2 = “ab”; 说明:直接在字符串常量池中创建一个字面量为"ab"的字符串。
- String s3 = “a” + “b”; 说明: s3指向字符串常量池中已经创建的"ab"的字符串。
- String s4 = s1.intern(); 说明:堆空间的s1对象在调用intern()之后,会将常量池中已经存在
的"ab"字符串赋值给s4。
1.4 常用的方法
- int length(): 返回字符串的长度: return value.length
- char charAt(int index): 返回某索引处的字符return value[index]
- boolean isEmpty(): 判断是否是空字符串: return value.length == 0
- String 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 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 - boolean endsWith(String suffix): 测试此字符串是否以指定的后缀结束
- boolean startsWith(String prefix): 测试此字符串是否以指定的前缀开始
- boolean startsWith(String prefix, int toffset): 测试此字符串从指定索引开始的子字符串是否
以指定前缀开始 - String replace(char oldChar, char newChar): 返回一个新的字符串, 它是通过用 newChar
替换此字符串中出现的所有 oldChar 得到的。 - 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个, 如果超过了, 剩下的全部都放到最后一个元素中。
@Test public void test1() { String s = "helloworld"; //获取字符串的长度 System.out.println("s的长度为:" + s.length()); //获取指定索引位置的字符 System.out.println("s.charAy(0)=" + s.charAt(0)); System.out.println("s.charAy(4)=" + s.charAt(4)); //返回指定字符在字符串中首次出现的索引位置 System.out.println("s.indexOf(l) = " + s.indexOf("l")); //返回指定字符串在字符串中首次出现的索引位置 System.out.println("s.indexOf(orl) = " + s.indexOf("orl")); //返回指定字符在此字符串中从指定位置后第一次出现处的索引 System.out.println("指定位置s.indexOf(l) = " + s.indexOf('l', 4)); System.out.println("指定位置s.indexOf(k)=" + s.indexOf('k', 0)); System.out.println("指定位置s.indexOf(l)=" + s.indexOf('l', 20)); System.out.println("指定位置s.indexOf(llo)=" + s.indexOf("llo", 1)); //从指定位置开始截取字符串,默认到尾部,即左闭右开 System.out.println("substring1 = " + s.substring(5)); System.out.println("substring2 = " + s.substring(5, 7));//包含5不包含7 //从指定位置开始到指定位置截取字符串,即左闭右开 System.out.println("substring3 = " + s.substring(3, 8)); System.out.println("substring4 = " + s.substring(0, s.length())); String s3 = " abc 123 "; System.out.println(s3.trim());//取出两端的空格 String s4 = "a,b,c,d,e,123"; String[] s5 = s4.split(",");//按逗号将字符串分开成字符数组 System.out.println(Arrays.toString(s5)); // for (int i = 0; i < s5.length; i++) { // System.out.println(s5[i]); // } } 运行结果如下 s的长度为:10 s.charAy(0)=h s.charAy(4)=o s.indexOf(l) = 2 s.indexOf(orl) = 6 指定位置s.indexOf(l) = 8 指定位置s.indexOf(k)=-1 指定位置s.indexOf(l)=-1 指定位置s.indexOf(llo)=2 substring1 = world substring2 = wo substring3 = lowor substring4 = helloworld abc 123 [a, b, c, d, e, 123]
2. StringBuffer和StringBuilder
2.1 简介:
- 当append和insert时,如果原来value数组长度不够,可扩容
- 如上这些方法支持方法链操作
- 方法链原理
2.2 常用的方法
● 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)
● public int length()
● public char charAt(int n )
● public void setCharAt(int n ,char ch)
2.3 区别
- StringBuilfer和StringBuffer非常相似但也有区别。
- 面试题:对比String、StringBuffer、StringBuilder
- String(jdk1.0)不可变数组final value[]
- StringBuffer(jdk1.0) 可变数组、效率低、线程安全
- StringBuilder(jdk5.0) 可变数组、效率高、线程不安全
不考虑多线程情况下优先使用StringBuilder
探究StringBuffer和StringBulider的高性能拼接 public class Test1 { @Test public void test1(){ //高效率字符串拼接 StringBuffer sb = new StringBuffer(); sb.append("hello ").append("world ").append("java ").append("python"); System.out.println(sb); } 下面是测试三者之间字符串拼接的速度的比较 @Test public void test2(){ String text = ""; long t1 = System.currentTimeMillis(); for (int i = 0; i < 20000; i++) { text += i; } long t2 = System.currentTimeMillis(); System.out.println(t2 - t1);//918 } @Test public void test3(){ StringBuffer stringBuffer = new StringBuffer(); long t1 = System.currentTimeMillis(); for (int i = 0; i < 20000; i++) { stringBuffer.append(i); } long t2 = System.currentTimeMillis(); System.out.println(t2 - t1);//3 } @Test public void test4(){ StringBuilder stringBuilder = new StringBuilder(); long t1 = System.currentTimeMillis(); for (int i = 0; i < 20000; i++) { stringBuilder.append(i); } long t2 = System.currentTimeMillis(); System.out.println(t2 - t1);//3 } }
3. 传统日期和时间处理
3.1 System类
System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间戳。
3.2 Date
表示特定的瞬间,精确到秒
-
构造器:
- **Date()**使用无参构造器创建对象可以获取本地当前的时间
- **Date(long date)**从那天起开始的date毫秒
-
常用方法
- getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。即时间戳
- toString():把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue,Wed, Thu, Fri, Sat), zzz是时间标准。
- 其它很多方法都过时了。
探究Date的使用 public class Test1 { @Test public void test1(){ System.currentTimeMillis();//系统时间戳 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");格式化对象 Date date = new Date();//当前时间 System.out.println("当前时间为: 北京时间" + sdf.format(date)); // System.out.println(date); Date date1 = new Date(100);//从1970-1-1 8:0:0开始的100毫秒后的时间 System.out.println(sdf.format(date1)); //时间戳 从某一时间开始到 1970-1-1 8:0:0的毫秒数 System.out.println(date1.getTime());时间戳 } }
3.3 SimpleDateFormat
Date类的API不易于国际化,大部分被废弃了,
常见的格式有;
- SimpleDateFormat() :默认的模式和语言环境创建对象
- public SimpleDateFormat(String pattern): 该构造方法可以用参数pattern指定的格式创建一个对象
- public String format(Date date): 方法格式化时间对象date
- public Date parse(String source): 从给定字符串的开始解析文本,以生成一个日期。
public class Test2 { @Test public void test2() throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //方式一 String dateStr = "1970-01-01 08:00:00.000";//将文档转换为标砖时间 Date date1 = sdf.parse(dateStr); // System.out.println(date1); System.out.println(sdf.format(date1)); System.out.println(date1.getTime());//打印时间戳 //方式二 String dateStr2 = "1970年01月01日"; SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日"); Date date2 = sdf1.parse(dateStr2); // System.out.println(date2); System.out.println(sdf1.format(date2)); System.out.println(date2.getTime());//打印时间戳 } } 运行结果展示 1970-01-01 08:00:00.000 0 1970年01月01日 -28800000
4. Calender
获取实例的方法:使用Calendar.getInstance()方法
获取字段:
- public void set(int field,int value) 设置field
- public void add(int field,int amount) 增加或减少时间
- public final Date getTime() 获取当前时间(区分上面的getTime())
- public final void setTime(Date date)
注意:月份是从0开始
星期日是0,星期一是1
public class Test3 { @Test public void test3() throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); Calendar c = Calendar.getInstance();//固定搭配,当前时间等价于 new Date() // //得到field // System.out.println(c.get(Calendar.YEAR));//得到年 // System.out.println(c.get(Calendar.MONTH));//得到月,传统的月份从零开始 // System.out.println(c.get(Calendar.DAY_OF_MONTH)); // System.out.println(c.get(Calendar.HOUR_OF_DAY)); //设置field c.set(Calendar.MONTH,0);//传统日期从0开始 System.out.println(sdf.format(c.getTime()));//得到date //减三个月 c.add(Calendar.MONTH,-3); System.out.println(sdf.format(c.getTime())); //创建1970-01-01 08:0:0;0.000; //方式一 String dateStr = "1970-01-01 08:0:0.0";//把字符串解析成日期 Date date1 = sdf.parse(dateStr); // System.out.println(date1.getTime());//显示时间戳 System.out.println(sdf.format(date1)); //方法二 Calendar c2 = Calendar.getInstance();//固定搭配 c2.set(1970,0,1,8,0,0); c2.set(Calendar.MILLISECOND,0); System.out.println(sdf.format(c2.getTime())); //当前时间四周后 Calendar c3 = Calendar.getInstance(); c3.add(Calendar.WEEK_OF_MONTH,5); System.out.println(sdf.format(c3.getTime())); } }
5. JDK新日期API
java8中引入了Java.time.API已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务
5.1 LocalDateTime和 Instant
public class Test4 { @Test public void test5(){ //得到当前时间 LocalDateTime l1 = LocalDateTime.now();//当前时间 System.out.println("l1 = " + l1); //得到field System.out.println(l1.getMonth().getValue()); System.out.println(l1.getYear()); System.out.println(l1.getDayOfMonth()); System.out.println(l1.get(ChronoField.HOUR_OF_DAY));//获取时间 //设置field,支持Chain方法链, LocalDateTime l2 = l1.withMonth(1).withDayOfMonth(1);//新API月份从1开始 System.out.println(l2); //加三个月三周 LocalDateTime l3 = l2.plusMonths(3).plusWeeks(3); System.out.println(l3); //减四周 System.out.println(l3.minusWeeks(4)); //创建1970-01-01 8:0:0 LocalDateTime l4 = LocalDateTime.of(1970, 1, 1, 0, 0, 0, 0); System.out.println(l4); //时间戳操作 Instant Instant i1 = l4.toInstant(ZoneOffset.UTC);//得到UTC时间的Instant System.out.println(i1.toEpochMilli()); LocalDateTime l5 = LocalDateTime.of(1970, 1, 1, 8, 0, 0, 0); Instant i2 = l5.toInstant(ZoneOffset.ofHours(8));//得到东八区的Instant System.out.println(i2.toEpochMilli());//时间戳为0 }
5.3 DateTimeFormatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒.SSS"); System.out.println(formatter.format(LocalDateTime.now()));