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: 反转内容
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) 之间。
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:不可变的任意精度的有符号十进制数
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

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 方法。

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 使用情况较多。

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()。

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:日期间隔
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
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
    }
}

容器

数组

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

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

集合

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


 上一篇
10. 集合 10. 集合
Collection概述在 java.util.Collection 中。是层级结构中的根接口,表示一组对象。Collection 是接口,但是在 JDK 中不提供此接口的任何实现,它提供了更为具体的子接口(如 Set,List) Col
2019-10-27
下一篇 
8. String 8. String
汉字进行 UTF-8 编码,每个汉字占3个字节。进行 GDK 编码,每个汉字占2个字节。ISO-8859-1 则占一个字节。 为什么要有包装类因为 Java 的某些特性和 API,例如泛型和集合,不支持基本数据类型,所以必须把基本数据类型转
2019-10-24
  目录