JavaSE基础(十三) - StringBuffer &
- 上半部分内容是继我的上一篇 JavaSE 基础(十一) 字符串的姊妹篇 ,大家可以对照来看。
- 本篇内容(Project && 笔记)大家需要的话大家可以到我的Github Github 链接 上 Clone。
1.String 高级
1.1 - StringBuffer 概述
- 是一个线程安全的可变字符序列。
- String 是一个不可变的字符序列,而 StringBuffer 是一个可变的字符序列。
读读 API 📖
A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified. At any point in time it contains some particular sequence of characters, but the length and content of the sequence can be changed through certain method calls.
String buffers are safe for use by multiple threads. The methods are synchronized where necessary so that all the operations on any particular instance behave as if they occur in some serial order that is consistent with the order of the method calls made by each of the individual threads involved.
1.2 - StringBuffer 构造方法
public StringBuffer()
构造一个不带字符的字符串缓冲区,初始容量为 16 个字节。
Constructs a string buffer with no characters in it and an initial capacity of 16 characters.
每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。从 JDK5 开始,为该类补充了一个单线程使用的等价类 StringBuilder
。与该类相比,通常应该优先使用 StringBuilder
,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。
As of release JDK 5, this class has been supplemented with an equivalent class designed for use by a single thread, StringBuilder. The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization.
-
StringBuffer(CharSequence suq)
构造一个字符串缓冲区,它包含与指定的charSequence
相同的字符。 -
public StringBuffer(String str)
容量为字符长度 + 初始容量
1.3 - StringBuffer 基本方法
-
public int length()
容器中的字符个数,实际值 -
public int capacity()
容器容量,理论值:字符串 length + 初始容量(16)
1.4 - StringBuffer 添加功能
-
public StringBuffer append(* *)
可以将任意类型数据添加到字符串缓冲区里面,并返回字符串缓冲区本身。
StringBuffer 是字符串缓冲区,当 new 的时候在堆内存创建了一个对象,底层是一个长度为 16 的字符数组,当调用添加方法时,不会再重新创建对象,而是在不断的向原缓冲区添加字符。
-
public StringBuffer insert(* *)
可以在指定索引插入任意类型数据,到字符串缓冲区里面,并返回字符串缓冲区本身。
插入到 insert 这个索引位置,其他字符串向后移。
1.5 - StringBuffer 删除功能
-
public StringBuffer deleteCharAt(int index)
根据索引删除某个字符。
当缓冲区中这个索引上没有元素时 👇
StringIndexOutOfBoundsException
-
public StringBuffer delete(int start, int end)
删除 [start, end) 包含头不包含尾。
清空缓冲区:sb.delete(0, sb.length())
1.6 - StingBuffer 替换、反转功能
-
public StringBuffer replace(int start, int end, String str)
替换 [start, end) 包含头不包含尾,String 的replace
方法可以转换指定字符。 -
public StringBuffer reverse()
将字符串反转。
1.7 - StringBuffer 截取功能
-
public String substring(int start, int end)
截取 [start, end) 字符,通过返回值返回截取的字符串。
原字符串缓冲区不被改变
1.8 - StringBuffer 与 String 相互转换
- String -> StringBuffer
- StringBuffer 构造方法:
public StringBuffer(String str)
- append 方法
- StringBuffer 构造方法:
- StringBuffer -> String
- 通过 String 构造方法,传入 StringBuffer 参数。
- 通过 toString()
- 通过 substring()
1.9 - Test 👨💻 输出数组
- 题目:输出结果[1, 2, 3],用 StringBuffer 实现
- 数据:int[] arr = {1, 2, 3}
private static String arrayToString(int[] arr) {
StringBuffer sb = new StringBuffer();
for (int I = 0; I < arr.length; I++) {
if (I == 0) {
// “+” 是通过创建 StringBuffer 对象 append 后 toString() 实现的。
sb.insert(0, “[“ + arr[i] + “, “);
} else if (I == arr.length - 1) {
sb.append(arr[i]).append(‘]’);
} else {
sb.append(arr[i]).append(“, “);
}
}
return sb.toString();
}
好处:只有一个 StringBuffer 对象,不会产生过多内存垃圾。
1.10 - Test 👨💻 字符串反转
- 题目:使用 StringBuffer,字符串反转。
public class Test2 {
public static void test() {
Scanner sc = new Scanner(System.in);
System.out.print(“Please enter a line: “);
String line = sc.nextLine();
String reverseLine = reverseString(line);
System.out.println(reverseLine);
}
private static String reverseString(String str) {
StringBuffer sb = new StringBuffer(str); // String -> StringBuffer
sb.reverse(); // 将缓冲区中内容反转
return sb.toString();
}
}
1.11 - StringBuffer 与 StringBuilder 区别
- StringBuffer 是 JDK1.0版本的,线程安全,效率低;StringBuilder 是 JDK1.5版本的,线程不安全,效率高。
- String 是一个不可变的字符序列。
1.12 - StringBuffer 与 StringBuilder 作为参数传递
- String 作为参数传递:String 虽然是引用数据类型,但是把它当做参数传递时,和基本数据类型是一样的。
- StringBuffer 作为参数传递:引用数据类型传递。
2.数组高级
2.1 - 冒泡排序
- 原理:两个相邻位做比较,小数向前移,大数向后移。
- 每次比较最大的被数移动到最后一位。
// 外层循环控制趟数,不参与运算,共比较 length - 1 趟。
for (int I = 0; I < arr.length - 1; I++) {
for (int j = 0; j < arr.length - 1 - I; j++) {
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j] ^ arr[j + 1];
arr[j + 1] = arr[j] ^ arr[j + 1];
arr[j] = arr[j] ^ arr[j + 1];
}
}
}
2.2 - 选择排序
- 用一个索引位置上的元素,依次与其他索引位置上的元素比较。
for (int I = 0; I < arr.length - 1; I++) {
for (int j = I + 1; j < arr.length; j++) {
if (arr[I] > arr[j]) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
}
2.3 - 二分查找
- 使用前提:数组是有序的。
public static int search_binary(int[] arr, int target) {
int min = 0;
int max = arr.length - 1;
int mid;
while (true) {
if (min > max) {
return -1;
}
mid = (min + max) / 2;
if (arr[mid] > target) {
max = mid - 1;
}
if (arr[mid] < target) {
min = mid + 1;
}
if (arr[mid] == target) {
return mid;
}
}
}
2.4 - Arrays 概述
-
public static String toString(int[] a)
数组 -> 字符串
读读原码 💡
public static String toString(int[] a) {
if (a == null)
// 如果传入数组是 null 返回 “null”
return “null”;
// 最大索引
int iMax = a.length - 1;
// 如果数组中没有元素,返回[]
if (iMax == -1)
return “[]”;
// 线程不安全,效率高
StringBuilder b = new StringBuilder();
// 将 ‘[‘ 添加到字符串缓冲区
b.append(‘[‘);
for (int I = 0; ; I++) {
// 将元素拼接到到字符串缓冲区
b.append(a[I]);
// 当输出为最后一个元素时,将 ‘]’ 拼接到字符串缓冲区
if (I == iMax)
return b.append(‘]’).toString();
// 在元素后,拼接 ‘]’ 到字符串缓冲区
b.append(“, “);
}
}
-
public static void sort(int[] a)
排序 -
private static int binarySearch(int[] a, int fromIndex, int toIndex, int key)
二分查找- 数组需要是有序的。
- 如果找不到则返回- (插入点 ) - 1。
- 如果数组中有多个要查找的值,不保证返回哪一个。
- 返回值 < 0 说明没有找到。
读读原码 💡
private static int binarySearch0(int[] a, int fromIndex, int toIndex, int key) {
// 最小索引 0
int low = fromIndex;
// 最大索引 length - 1
int high = toIndex - 1;
// 最小索引 <= 最大索引 作为循环判断
while (low <= high) {
// >>> 求出中间索引值
int mid = (low + high) >>> 1;
// 通过中间索引获取中间值
int midVal = a[mid];
// 查找值在中间值右侧
if (midVal < key)
// 最小索引变化
low = mid + 1;
// 查找值在中间值左侧
else if (midVal > key)
high = mid - 1;
else
// 中间值 == 查找值
return mid; // key found
}
// 如果跳出循环,说明符合 low <= high 条件,没有找到返回 -(low + 1)
return -(low + 1); // key not found.
}
3.Integer 基本数据类型包装类
3.1 - Integer 概述
- 将基本数据类型封装成对象的好处在于,可以在对象中定义更多的功能方法操作数据
- 常用操作之一:用于基本数据类型与字符串之间的转换。
byte -> Byte
short -> Short
int -> Integer
long -> Long
float -> Float
double -> Double
char -> Character
boolean -> Boolean
3.2 - 进制转换
-
public static String toBinaryString(int i)
转二进制。 -
public static String toHexString(int i)
转十六进制。 -
public static String toOctalString(int i)
转八进制。
3.3 - 常量及构造方法
-
public static final int MAX_VALUE
最大 int 数。 -
public static final int MIN_VALUE
最小 int 数 -
public Integer(int value)
int 构造。 -
public Integer(String s) throws NumberFormatException
String 构造
Integer i = new Integer("abc");
NumberFormatException:数字格式异常
3.4 - int 与 String 互相转换
- int -> String
int i1 = 100;
Integer i2 = new Integer(i1);
// 第一种
String s1 = i1 + "";
// 第二种
String s2 = String.valueOf(i1);
// 第三种
String s3 = i2.toString();
// 第四种
String s4 = Integer.toString(i1);
- String -> int
基本数据类型包装类有 8 种,其中 7 种都有parseX
方法,可以用来将字符串转换为基本数据类型。char 的包装类中没有parseX
,通过 String 的toCharArray()
将字符串转换为字符数组。
String s = "200";
// 第一种
int i1 = new Integer(s).intValue;
// 第二种
int i2 = Integer.parseInt(s);
3.5 - 拆装箱
-
JDK1.5新特性
-
自动装箱:把基本数据类型 -> 包装数据类型
Integer i = 100;
-
自动拆箱:包装数据类型 -> 把基本数据类型
int a = i;
注意事项:
Integer i = null;
,底层用 i 调用intValue()
NullPointerException
3.6 - 面试题
- 自动装箱创建 Integer 重新创建对象问题。
{
Integer i1 = 97;
Integer i2 = 97;
System.out.println(i1 == i2); // true
System.out.println(i1.equals(i2)); // true
}
{
Integer i1 = 128;
Integer i2 = 128;
System.out.println(i1 == i2); // false
System.out.println(i1.equals(i2)); // true
}
通过自动装箱创建 Integer,如果没有超过 byte 取值范围,就不会自动创建对象。而是从常量池中取,如果超过了 byte 取值范围,则会重新创建对象。
悄悄话 🌈
- 今天第一次上传了 project 和 PDF 笔记,不知道对大家学习有没有帮助,大家可以在简书给我或者我的 Github 仓库下给我留言,有好的建议的话,在下次专题文章中我都会采纳的🐳。
- 现在每天的学习任务越来越重了,因为昨天放假一天,自己预习的时候整理好的笔记,今天上课和自习的时候又排了一下版面,还剩不多时间预习明天内容了,先不说了小伙伴们,我要去准备预习下明天内容了,大家晚安。
彩蛋 🐣
-
最近开通了简书专题 JavaSE 成长之路,主要为一样正在 JavaSE 修行中的简友们提供了技术交流的平台,希望大家多多投稿交流互动。
-
👇Project
-
👇Note