9. StringBuffer

StringBuffer

String 类型是不可变的字符序列,所以又配备了另一个类 StringBufer,它是可变的字符序列。StringBufer 有称为字符串缓冲区。内部用 char 数组存储。

  1. StringBuffer 采用 char 数组实现,那么长度是多少?

    StringBuffer(): 默认长度为 16

    StringBuffer(String str): 长度为 str 的长度 + 16

    StringBuffer(int capacity): 默认长度通过 capacity 指定

  2. char 数组如何实现增长?

    会先将 value 的数组扩大为 value.length *2 +2 的长度。如果还不够那么就按照实际所需的大小来设置。

注意:

  1. StringBuffer 创建对象必须使用 new,String 可以直接 String aa = “11”;
  2. StringBuffer 中的拼接不能直接用 + , 可以使用 append

常用方法

  1. append:用于追加内容
  2. insert: 插入内容
  3. delete:删除内容
  4. reverse: 反转内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.itguigu.com;

import org.junit.Test;

public class TestStringBuffer {
@Test
public void test5() {
StringBuffer sBuffer = new StringBuffer("hello");
sBuffer.reverse();
System.out.println(sBuffer); // olleh
}

@Test
public void test4() {
StringBuffer sBuffer = new StringBuffer("hello");
sBuffer.delete(2, 5);
System.out.println(sBuffer); // he
}

@Test
public void test3() {
StringBuffer sBuffer = new StringBuffer("hello");
sBuffer.insert(2, "world");
System.out.println(sBuffer); // heworldllo
}

@Test
public void test2() {
StringBuffer sBuffer = new StringBuffer();
sBuffer.append(1).append(2).append(3);
System.out.println(sBuffer); // 123
}

@Test
public void test() {
String string = "hello";
StringBuffer sBuffer = new StringBuffer("hello");

change(string, sBuffer);

System.out.println(string); // 输出 hello,因为 String 的不可变性
System.out.println(sBuffer); // 输出 helloworld
}

public void change(String string, StringBuffer sBuilder) {
string +="world";
sBuilder.append("world"); // 使用 append 进行追加内容
}
}

StringBuilder

JDK 1.5 之后增加的功能。StringBuilder 与 StringBuffer 的 API (方法) 完全一样,但是 StringBuilder 不保证同步,也就是说 StringBuffer 是线程安全的,StringBuilder 是线程不安全的。即当前多个线程来使用同一个 StringBuilder 对象时候,是不安全的。而多个线程来使用同一个 StringBuffer 对象时候,是安全的。单线程情况下建议使用 StringBuilder,因为速度要快些。

System

System 有三个常量对象:System.in, System.out, System.err。System.in 的类型是 InputStream,System.out 和 System.err 的类型是 PrintStrem。

  1. System.currentTimeMillis(): 当前时间距 1970 年 1 月 1日之间的时间差的毫秒值。

  2. System.arraycopy(src, srcPost, dest, destPost, len): 可参考此处

  3. System.gc(): 通知垃圾回收器进行垃圾回收,但不是立即进行。

Runtime

代表运行环境,Runtime.gc() 和 System.gc() 是一样的。

  1. Runtime.maxmemory(): 获取当前 Java 虚拟机中的内存总量

  2. Runtime.freeMemory(): 获取空闲内存

  3. Runtime.totalMemory(): 获取 Java 虚拟机试图使用的最大内存量

Math

和数学运算相关。

  1. PI
  2. sqrt(x): 求平方根
  3. pow(x, y): 求 x 的 y 次方
  4. round(x): 四舍五入
  5. ceil(x):向上取整
  6. floor(x):往下取整
  7. max(x, y):最大值
  8. min(x, y):最小值
  9. random():随机数,范围是 0到1,但是不包含1。java.util.Random 类则是专门用来生成随机数的,常用的方法有三个。nextDouble() 生成的随机数范围在 [0, 1) 之间,nextInt() 生成随机数的范围是整个 Int 的取值范围,nextInt(int n) 的取值则是 [0, n) 之间。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.itguigu.com;

import java.util.Random;

import org.junit.Test;

public class TestMach {
@Test
public void test() {
System.out.println(Math.sqrt(4));
System.out.println(Math.pow(2, 3));
System.out.println(Math.ceil(2.3));
System.out.println(Math.round(2.6));
System.out.println(Math.floor(2.9));
System.out.println(Math.max(20, 11));
System.out.println(Math.min(20, 11));

Random random = new Random();
System.out.println(random.nextDouble());
System.out.println(random.nextInt());
System.out.println(random.nextInt(1000));

/**
* 2.0
* 8.0
* 3.0
* 3
* 2.0
* 20
* 11
* 0.4742139352009622
* 56990359
* 270
*/
}
}

java.math

  1. BigInteger:大整数。可以表示不可变的任意精度的整数
  2. BigDecimal:不可变的任意精度的有符号十进制数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.itguigu.com;

import java.math.BigInteger;

import org.junit.Test;

public class TestJavaMath {
@Test
public void test() {
BigInteger bigInteger = new BigInteger("87234097240724720472047024223424456464646");
BigInteger bigInteger2 = new BigInteger("734587385738075037503957305703570357305");

System.out.println(bigInteger.add(bigInteger2));
System.out.println(bigInteger.subtract(bigInteger2));
System.out.println(bigInteger.multiply(bigInteger2));
System.out.println(bigInteger.divide(bigInteger2));
}
}

日期时间

日期时间API:

第一代:java.util.Date

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.itguigu.com;

import java.util.Date;

import org.junit.Test;

public class TestDate {
@Test
public void test() {
Date date = new Date();
System.out.println(date); // Wed Oct 23 21:38:49 CST 2019

long time = date.getTime(); // 获取当前时间戳,功能和 system.currentTimeMillis 一样
System.out.println(time); // 1571837944083

Date date2 = new Date(time);// 将时间戳转换为时间格式
System.out.println(date2); // Wed Oct 23 21:39:04 CST 2019
}
}

第二代:java.util.Calendar

Calendar 是抽象类,无法直接 new 对象,但是我们可以 new 它的子类对象 GregorianCalendar,或者使用其中的获取实例 getInstance 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.itguigu.com;

import java.util.Calendar;

import org.junit.Test;

public class TestDate {
@Test
public void test() {
Calendar instance = Calendar.getInstance();
int year = instance.get(Calendar.YEAR);
int month = instance.get(Calendar.MONTH); // 月的值从 0 开始计算
int day = instance.get(Calendar.DAY_OF_MONTH);
System.out.println(year +"年"+ month + "月" + day + "日"); // 2019年9月23日
}
}

将日期格式转换为字符串,或者将字符串转换为日期格式。我们使用的是 java.text.DateFormat。但是 DateFormat也是一个抽象类,也是无法直接 new 对象,DateFormat 也提供了两种获取到对象的方法,分别是 new 它的子类 SimpleDateFormat 或者使用 getInstance 方法。通常 SimpleDateFormat 使用情况较多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.itguigu.com;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.junit.Test;

public class TestDate {
@Test
public void test() throws ParseException {
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String dateFormat = simpleDateFormat.format(date); // 将时间格式转为字符串
Date dateParse = simpleDateFormat.parse(dateFormat);// 将字符串转换为时间

System.out.println(dateFormat); // 2019-10-23 22:05:18
System.out.println(dateParse); // Wed Oct 23 22:05:18 CST 2019
}
}

第三代:JDK1.8 之后才有。主要变动为将时间对象设计为了不可变的对象,即每个时间点都是一个时间对象,且不能改变。在新版本中还解决了闰秒的问题。

  1. LocalDate: 只能表示日期
  2. LocalTime:只能表示时间
  3. LocalDateTime: 可以表示日期时间

三个 API(LocalDate,LocalTime,LocalDateTime)大部分都含有以下常用的方法,now(),of(), getYear(), getXXX(), withXXX(), plusXXX(), minusXXX(), isLeapYear()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.itguigu.com;

import java.time.LocalDate;
import java.time.LocalDateTime;

import org.junit.Test;

public class TestDate {
@Test
public void test(){
// 获取当前日期
LocalDate now = LocalDate.now();
System.out.println(now);
// 创建一个日期
LocalDate birth = LocalDate.of(1999, 9, 9);
// 获取日期的年
int year = birth.getYear();
// 获取日期的月, 也是从0开始
int month = birth.getMonthValue();

System.out.println(birth);
System.out.println(year);
System.out.println(month);

// 修改年份,返回新对象
LocalDate newYear = birth.withYear(2000);
System.out.println(newYear);

// 增加天数
LocalDate plusDays = now.plusDays(123);
System.out.println(plusDays);

// 减少天数
LocalDate minusDays = plusDays.minusDays(123);
System.out.println(minusDays);

// 判断是否为闰年
boolean leapYear = now.isLeapYear();
System.out.println(leapYear);

// 获取当前的时间
LocalDateTime now2 = LocalDateTime.now();
System.out.println(now2);
}
}
  1. Duration: 时间间隔
  2. Period:日期间隔
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.itguigu.com;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;

import org.junit.Test;

public class TestDate {
@Test
public void test(){
LocalTime now = LocalTime.now();
LocalTime noeOf = LocalTime.of(23, 00, 00);
Duration between = Duration.between(noeOf, now); // 计算现在时间到 23:00:00 还差多少
System.out.println(between); // PT-10M0.266S

LocalDate now2 = LocalDate.now();
LocalDate of = LocalDate.of(2019, 12, 31);
Period between2 = Period.between(of, now2); // 计算现在的日期到 2019-12-31 还差多少
System.out.println(between2); // P-2M-8D
}
}
  1. DateTimeFormatter: 格式化时间格式,支持两种模式,一种内置的预定义模式 ofLocalizedDate, 另一种为自定义模式 ofPattern
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.itguigu.com;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

import org.junit.Test;

public class TestDate {
@Test
public void test(){
LocalDate now = LocalDate.now(); // 当前日期
DateTimeFormatter d1 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
DateTimeFormatter d2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
DateTimeFormatter d3 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);

System.out.println(d1.format(now)); // 2019年10月23日 星期三
System.out.println(d2.format(now)); // 19-10-23
System.out.println(d3.format(now)); // 2019-10-23

LocalDateTime now2 = LocalDateTime.now(); // 当前时间日期
DateTimeFormatter d4 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");// 自定义格式
System.out.println(d4.format(now2)); // 2019-10-23 23:12:22
}
}

容器

数组

优点:可以根据索引快速定位某个元素,访问速度快

缺点:长度是固定的,需要考虑扩容,并且删除和插入元素时需要移动元素。需要单独的变量来辅助记录实际有效的元素个数。所以数组常用来存储基本数据类型。

集合

栈,队列,链表,堆,图……