原文地址:https://www.cloudcrossing.xyz/post/39/
1 StringBuffer类
1.1 StringBuffer类概述
目前用String类做拼接,每次都会构建一个新的String类对象,比较耗时耗内存,而这种拼接操作比较常见,因此java提供了StringBuffer类(字符串缓冲区类)。
StringBuffer类的对象能够被多次的修改(长度和内容),并且不产生新的未使用对象。StringBuilder 类在 Java 5 中被提出,它是线程安全(不能同步访问)的可变字符序列。
StringBuffer类的构造方法:
- A:public StringBuffer():无参构造方法,其初始容量为16个字符
- B:public StringBuffer(int size):指定容量的字符串缓冲区对象
- C:public StringBuffer(String str):指定字符串内容的字符串缓冲区对象,其初始容量为
16+ length(str)
StringBuffer类的方法:
- A:public int capacity():返回当前容量(理论值)
- B:public int length():返回长度,字符数(实际值)
public class StringBufferDemo {
public static void main(String[] args) {
// public StringBuffer():无参构造方法
StringBuffer sb = new StringBuffer();
System.out.println("sb:" + sb);
System.out.println("sb.capacity():" + sb.capacity());
System.out.println("sb.length():" + sb.length());
System.out.println("--------------------------");
// public StringBuffer(int capacity):指定容量的字符串缓冲区对象
StringBuffer sb2 = new StringBuffer(50);
System.out.println("sb2:" + sb2);
System.out.println("sb2.capacity():" + sb2.capacity());
System.out.println("sb2.length():" + sb2.length());
System.out.println("--------------------------");
// public StringBuffer(String str):指定字符串内容的字符串缓冲区对象
StringBuffer sb3 = new StringBuffer("hello");
System.out.println("sb3:" + sb3);
System.out.println("sb3.capacity():" + sb3.capacity());
System.out.println("sb3.length():" + sb3.length());
}
}
//运行结果:
sb:
sb.capacity():16
sb.length():0
--------------------------
sb2:
sb2.capacity():50
sb2.length():0
--------------------------
sb3:hello
sb3.capacity():21
sb3.length():5
1.2 StringBuffer的常见方法
添加方法:
- public StringBuffer append(String str):可以把任意类型数据添加到字符串缓冲区中,并返回字符串缓冲区本身
- public StringBuffer insert(int offset, String str):在指定位置把任意类型的数据添加到字符串缓冲区中,并返回字符串缓冲区本身
public class StringBufferDemo {
public static void main(String[] args) {
// 创建字符串缓冲区对象
StringBuffer sb = new StringBuffer();
// public StringBuffer append(String str)
StringBuffer sb2 = sb.append("hello");
System.out.println("sb:" + sb); //调用的是StringBuffer类的toString方法
System.out.println("sb2:" + sb2);
System.out.println(sb == sb2); // true
// 一步一步的添加数据
sb.append(true);
sb.append(12);
sb.append(34.56);
System.out.println("sb:" + sb);
// 链式编程
StringBuffer sb3 = new StringBuffer();
sb3.append("hello").append(true).append(12).append(34.56);
System.out.println("sb3:" + sb3);
System.out.println(sb3 == sb1); // false
// public StringBuffer insert(int offset,String str)
sb.insert(5, "world");
System.out.println("sb:" + sb);
System.out.println(sb == sb2);
System.out.println("sb2:" + sb2);
}
}
//运行结果:
sb:hello
sb2:hello
true
sb:hellotrue1234.56
sb3:hellotrue1234.56
false
sb:helloworldhellotrue1234.56
true
sb2:helloworldtrue1234.56
删除方法:
- A:public StringBuffer deleteCharAt(int index):删除指定位置的字符,并返回本身
- B:public StringBuffer delete(int start, int end):删除从指定位置start(包含)开始到指定位置end结束(不包含)的字符,并返回本身
public class StringBufferDemo {
public static void main(String[] args) {
// 创建对象
StringBuffer sb = new StringBuffer();
// 添加功能
sb.append("hello").append("world").append("java");
System.out.println("sb:" + sb);
// public StringBuffer deleteCharAt(int index):删除指定位置的字符,并返回本身
// 需求:删除 e 这个字符
// sb.deleteCharAt(1);
// 需求:删除第一个 l 这个字符
// sb.deleteCharAt(1);
// public StringBuffer delete(int start,int end):删除从指定位置开始指定位置结束的内容,并返回本身
// 需求:我要删除world这个字符串,肿么办?
// sb.delete(5, 10);
// 需求:我要删除所有的数据
sb.delete(0, sb.length());
System.out.println("sb:" + sb);
}
}
替换方法:
- public StringBuffer replace(int start, int end, String str):从start(包含)开始到end(不包含)用str替换(如果需要,序列将延长以适应指定的字符串)
public class StringBufferDemo {
public static void main(String[] args) {
// 创建字符串缓冲区对象
StringBuffer sb = new StringBuffer();
// 添加数据
sb.append("hello");
sb.append("world");
sb.append("java");
System.out.println("sb:" + sb);
// public StringBuffer replace(int start,int end,String str):从start开始到end用str替换
// 需求:把world这个数据替换为"节日快乐"
sb.replace(5, 10, "节日快乐");
System.out.println("sb:" + sb);
}
}
反转方法:
- public StringBuffer reverse():将此字符序列用其反转形式取代,返回本身(即返回本身的一个引用)
public class StringBufferDemo {
public static void main(String[] args) {
// 创建字符串缓冲区对象
StringBuffer sb = new StringBuffer();
// 添加数据
sb.append("霞青林爱我");
System.out.println("sb:" + sb);
// public StringBuffer reverse()
sb.reverse();
System.out.println("sb:" + sb); //sb:我爱林青霞
}
}
判断一个字符串是否是对称字符串,例如"abc"不是对称字符串,"aba"、"abba"、"aaa"、"mnanm"是对称字符串。
import java.util.Scanner;
public class StringBufferTest4 {
public static void main(String[] args) {
// 创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String s = sc.nextLine();
//用字符串缓冲区的反转功能
boolean b2 = isSame(s);
System.out.println("b2:"+b2);
}
public static boolean isSame(String s) {
return new StringBuffer(s).reverse().toString().equals(s);
}
截取方法:
- A:public String substring(int start):返回从指定位置开始(包含)到末尾的子字符串
- B:public String substring(int start, int end):返回从指定位置开始(包含)到指定位置结束(不包含,即end-1)的子字符串
注意:返回值类型不再是StringBuffer本身了,StringBuffer本身不发生改变
public class StringBufferDemo {
public static void main(String[] args) {
// 创建字符串缓冲区对象
StringBuffer sb = new StringBuffer();
// 添加元素
sb.append("hello").append("world").append("java");
System.out.println("sb:" + sb);
// 截取功能
// public String substring(int start)
String s = sb.substring(5);
System.out.println("s:" + s);
System.out.println("sb:" + sb);
// public String substring(int start,int end)
String ss = sb.substring(5, 10);
System.out.println("ss:" + ss);
System.out.println("sb:" + sb);
}
}
//运行结果:
sb:helloworldjava
s:worldjava
sb:helloworldjava
ss:world
sb:helloworldjava
1.3 StringBuffer类与String类的转换
类之间的转换:
- A --> B的转换:我们把A转换为B,其实是为了使用B的功能
- B --> A的转换:我们可能要的结果是A类型,所以还得转回来
String和StringBuffer相互转换:
- A:String --> StringBuffer:通过构造方法
- B:StringBuffer --> String:通过toString()方法
public class StringBufferTest {
public static void main(String[] args) {
// String --> StringBuffer
String s = "hello";
// 注意:不能把字符串的值直接赋值给StringBuffer
// StringBuffer sb = "hello";
// StringBuffer sb = s;
// 方式1:通过构造方法
StringBuffer sb = new StringBuffer(s);
// 方式2:通过append()方法
StringBuffer sb2 = new StringBuffer();
sb2.append(s);
System.out.println("sb:" + sb);
System.out.println("sb2:" + sb2);
System.out.println("---------------");
// StringBuffer --> String
StringBuffer buffer = new StringBuffer("java");
// String(StringBuffer buffer)
// 方式1:通过构造方法
String str = new String(buffer);
// 方式2:通过toString()方法
String str2 = buffer.toString();
System.out.println("str:" + str);
System.out.println("str2:" + str2);
}
}
1.4 StringBuffer类的面试题
1:String,StringBuffer,StringBuilder的区别?
- A:String是内容不可变的,而StringBuffer、StringBuilder都是内容可变的
- B:StringBuffer是同步的,数据安全,效率低;StringBuilder是不同步的,数据不安全,效率高
- C:由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下(比如单线程)建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类
2:StringBuffer和数组的区别?
- A:二者都可以看出是一个容器,装其他的数据
- B:但是StringBuffer的数据最终是一个字符串数据
- C:而数组可以放置多种数据,但必须是同一种数据类型的
3:形式参数问题
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
String s1 = "A";
String s2 = "B";
System.out.println(s1 + "---" + s2);// A---B
change(s1, s2);
System.out.println(s1 + "---" + s2);// A---B
StringBuffer sb1 = new StringBuffer("A");
StringBuffer sb2 = new StringBuffer("B");
System.out.println(sb1 + "---" + sb2);// A---B
change(sb1, sb2);
System.out.println(sb1 + "---" + sb2);// AB---B
}
public static void change(StringBuffer x, StringBuffer y) {
x.append(y);
x = y;
}
public static void change(String s1, String s2) {
s1 = s2;
s2 = s1 + s2;
}
}
可以看出,String作为参数传递,效果和基本类型作为参数传递是一样的。
而变量是 sb1、sb2、x、y 中存储的是StringBuffer变量的引用而不是一个StringBuffer对象。根据引用类型参数传递的规则,operate接收的参数只是StringBuffer对象的引用。
因此可以理解为 sb1、x 都是指向同一个对象;sb2、y 也是指向同一个StringBuffer对象,所以x.append(y)将导致 x 和 sb1 同指的StringBuffer对象改变(增加"B")。
而 y=x 只是让变量 y 改变指向为和 x 相同的StringBuffer对象,y 原来所指的对象并不会发生任何改变。即StringBuffer作为引用类型参数传递。
2 数组进阶以及Arrays类
2.1 排序
冒泡排序:相邻元素两两比较,大的往后放,一次排序完成后,数组中最大值落在最大索引处。同理,其他元素也如此。总共需要 length-1 次排序。
public static void sort1(int[] arr) {
for (int x = 0; x < arr.length - 1; x++) {
for (int y = 0; y < arr.length - 1 - x; y++) {
if (arr[y] > arr[y + 1]) {
int temp = arr[y];
arr[y] = arr[y + 1];
arr[y + 1] = temp;
}
}
}
}
选择排序:从0索引开始,依次和后面的元素两两比较,小的往后放,一次排序完成后,数组中最小值在最小索引处。同理,其他元素也如此。总共需要 length-1 次排序。
public static void sort2(int[] arr) {
for (int x = 0; x < arr.length - 1; x++) {
for (int y = x + 1; y < arr.length; y++) {
if (arr[x] > arr[y]) {
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
}
}
}
2.2 查找
基本查找:针对数组无序的情况。
public static int find1(int[] arr, int value) {
int index = -1;
for (int x = 0; x < arr.length; x++) {
if (arr[x] == value) {
index = x;
break;
}
}
return index;
}
二分查找:针对数组有序的情况。
public static int binarySearch(int[] arr,int value) {
int min = 0;
int max = arr.length-1;
int mid = (min+max)/2;
while(arr[mid] != value) {
if(arr[mid] > value) {
max = mid - 1;
}else if(arr[mid] < value) {
min = mid + 1;
}
if(min > max) {
return -1;
}
mid = (min+max)/2;
}
return mid;
}
2.3 Arrays工具类
Arrays工具类是针对数组进行操作的工具类,包括排序和查找等功能。
- A:public static String toString(int[] a):把数组转换成字符串
- B:public static void sort(int[] a):对数组进行快速排序
- C:public static int binarySearch(int[] a, int key):二分查找
private static int binarySearch0(int[] a, int fromIndex, int toIndex, int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1; //相当于除以2
int midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
注意Arrays工具类的二分查找,如果找不到指定的值返回的不是-1.
public class ArraysDemo {
public static void main(String[] args) {
// 定义一个数组
int[] arr = { 24, 69, 80, 57, 13 };
// public static String toString(int[] a) 把数组转成字符串
System.out.println("排序前:" + Arrays.toString(arr));
// public static void sort(int[] a) 对数组进行排序
Arrays.sort(arr);
System.out.println("排序后:" + Arrays.toString(arr));
// [13, 24, 57, 69, 80]
// public static int binarySearch(int[] a,int key) 二分查找
System.out.println("binarySearch:" + Arrays.binarySearch(arr, 57));
System.out.println("binarySearch:" + Arrays.binarySearch(arr, 577));
}
}
3 基本类型包装类
3.1 基本类型包装类概述
为了让基本类型的数据进行更多的操作,Java就为每种基本类型提供了对应的包装类类型。
将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据。常用的操作之一为:用于基本数据类型与字符串之间的转换。
3.2 Integer类概述及其构造方法
Integer类在对象中包装了一个基本类型int的值,其提供了多个方法,能在int类型和String类型之间互相转换,还提供了处理int类型时非常有用的常量和方法。
构造方法:
- A:public Integer(int value)
- B:public Integer(String str)(注意:这个字符串必须是由数字字符组成)
public class IntegerDemo {
public static void main(String[] args) {
// 方式1
int i = 100;
Integer ii = new Integer(i);
System.out.println("ii:" + ii);
// 方式2
String s = "100";
// String s = "abc"; // NumberFormatException
Integer iii = new Integer(s);
System.out.println("iii:" + iii);
}
}
3.3 String和int的相互转换
- A:String --> int:String.valueof(num)
- B:int --> String:Integer.praseInt(str)
public class IntegerDemo {
public static void main(String[] args) {
// int to String
int number = 100;
// 方式1
String s1 = "" + number;
System.out.println("s1:" + s1);
// 方式2
String s2 = String.valueOf(number);
System.out.println("s2:" + s2);
// 方式3
// Integer.toString
Integer i = new Integer(number);
String s3 = i.toString();
System.out.println("s3:" + s3);
// 方式4
// public static String toString(int i)
String s4 = Integer.toString(number);
System.out.println("s4:" + s4);
System.out.println("-----------------");
// String to int
String s = "100";
// 方式1
// String -- Integer -- int
Integer ii = new Integer(s);
// public int intValue()
int x = ii.intValue();
System.out.println("x:" + x);
//方式2
//public static int parseInt(String s)
int y = Integer.parseInt(s);
System.out.println("y:"+y);
}
}
3.4 Integer类的进制转换
常用的基本进制转换:
- public static String toBinaryString(int i)
- public static String toOctalString(int i)
- public static String toHexString(int i)
十进制到其他进制:public static String toString(int i,int radix)。注意:radix(进制)的范围:2-36。
其他进制到十进制:public static int parseInt(String s,int radix)。
public class IntegerDemo {
public static void main(String[] args) {
// 十进制到二进制,八进制,十六进制
System.out.println(Integer.toBinaryString(100));
System.out.println(Integer.toOctalString(100));
System.out.println(Integer.toHexString(100));
System.out.println("-------------------------");
// 十进制到其他进制
System.out.println(Integer.toString(100, 10));
System.out.println(Integer.toString(100, 2));
System.out.println(Integer.toString(100, 8));
System.out.println(Integer.toString(100, 16));
System.out.println("-------------------------");
//其他进制到十进制
System.out.println(Integer.parseInt("100", 10));
System.out.println(Integer.parseInt("100", 2));
System.out.println(Integer.parseInt("100", 8));
System.out.println(Integer.parseInt("100", 16));
}
}
3.5 自动装箱与自动拆箱
自动装箱与自动拆箱是JDK5的新特性。
- 自动装箱:基本类型to引用类型
- 自动拆箱:引用类型to基本类型
public class IntegerDemo {
public static void main(String[] args) {
// 定义了一个int类型的包装类类型变量
// Integer i = new Integer(100);
Integer ii = 100;
ii += 200;
System.out.println("ii:" + ii);
// 通过反编译后的代码
// Integer ii = Integer.valueOf(100); //自动装箱
// ii = Integer.valueOf(ii.intValue() + 200); //自动拆箱,再自动装箱
// System.out.println((new StringBuilder("ii:")).append(ii).toString());
Integer iii = null; // NullPointerException。建议先判断是否为null,然后再使用。
if (iii != null) {
iii += 1000;
System.out.println(iii);
}
}
}
最后补充一下:
public class Demo {
public static void main(String[] args) {
Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2); //false
System.out.println(i1.equals(i2)); //true
System.out.println("-----------");
Integer i3 = new Integer(128);
Integer i4 = new Integer(128);
System.out.println(i3 == i4); //false
System.out.println(i3.equals(i4)); //true
System.out.println("-----------");
Integer i5 = 128;
Integer i6 = 128;
System.out.println(i5 == i6); //false
System.out.println(i5.equals(i6)); //true
System.out.println("-----------");
Integer i7 = 127;
Integer i8 = 127;
System.out.println(i7 == i8); //true
System.out.println(i7.equals(i8)); //true
}
}
通过查看源码,我们就知道了,针对-128到127之间的数据,做了一个数据缓冲池,如果数据是该范围内的,每次并不创建新的空间。当在 -128~127之外才重新 new Integer(i);
。
3.6 Character类
Character 类在对象中包装一个基本类型 char 的值。此外,该类提供了几种方法,以确定字符的类别(小写字母,数字,等等),并将字符从大写转换成小写,反之亦然。
构造方法:public Character(char value)
public class CharacterDemo {
public static void main(String[] args) {
// 创建对象
Character ch = new Character('a');
System.out.println("ch:" + ch);
}
}
常用的几个方法:
- public static boolean isUpperCase(char ch):判断给定的字符是否是大写字符
- public static boolean isLowerCase(char ch):判断给定的字符是否是小写字符
- public static boolean isDigit(char ch):判断给定的字符是否是数字字符
- public static char toUpperCase(char ch):把给定的字符转换为大写字符
- public static char toLowerCase(char ch):把给定的字符转换为小写字符
举个例子:统计一个字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)。
分析:
- A:定义三个统计变量。
- int bigCont=0;
- int smalCount=0;
- int numberCount=0;
- B:键盘录入一个字符串
- C:把字符串转换为字符数组。
- D:遍历字符数组获取到每一个字符
- E:判断该字符是
- 大写 bigCount++;
- 小写 smalCount++;
- 数字 numberCount++;
- F:输出结果即可
import java.util.Scanner;
public class CharacterTest {
public static void main(String[] args) {
// 定义三个统计变量。
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
// 键盘录入一个字符串。
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
// 把字符串转换为字符数组。
char[] chs = line.toCharArray();
// 历字符数组获取到每一个字符
for (int x = 0; x < chs.length; x++) {
char ch = chs[x];
// 判断该字符
if (Character.isUpperCase(ch)) {
bigCount++;
} else if (Character.isLowerCase(ch)) {
smallCount++;
} else if (Character.isDigit(ch)) {
numberCount++;
}
}
// 输出结果即可
System.out.println("大写字母:" + bigCount + "个");
System.out.println("小写字母:" + smallCount + "个");
System.out.println("数字字符:" + numberCount + "个");
}
}
网友评论