当前位置:网站首页>可变字符串
可变字符串
2022-08-04 01:25:00 【保护奶猫】
可变字符串
可变字符串采用toString()转化为不可变字符串(转换后用于比较值是否相等)
因为String类在创建对象时,值不可变。在频繁更新值时就是在内存中频繁创建对象,效率很低。这时就需要可变字符串
运行下面代码,我们就可以发现其效率差距,能清晰看出String在频繁更新时的效率低,浪费内存空间
String str = "";
long begin = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
str += i;
}
long end = System.currentTimeMillis();
//输出的是循环所用时间
System.out.println(end - begin);
StringBuilder sb = new StringBuilder();
long begin = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
sb.append(i);
}
long end = System.currentTimeMillis();
//输出的是循环所用时间
System.out.println(end - begin);
StringBuilder类
概念
用于表示可变字符串的一个类,是非线程安全的,建议在单线程环境下使用,效率略高于
StringBuffer。
构造方法 | |
---|---|
new StringBuilder() | 默认创建一个长度为16的字符数组 |
new StringBuilder(int i) | 创建一个长度为i的字符数组 |
new StringBuilder(String str) | 创建一个长度为str.length()+16的数组 |
StringBuilder sb = new StringBuilder();
sb.append("xjc");
sb.append(123);
sb.append(4.0);
sb.append(new Random());
System.out.println(sb);
xjc1234.0java.util.Random@74a14482
根据结果可以看出append()是用于字符串添加内容,可以是任何内容
常用方法(在使用 StringBuilder 类时,每次都会对 StringBuilder 对象本身进行操作,而不是生成新的对象,不同于String的方法,调用后结果不变):
sb.append("qwert");
//删除[0,3)
sb.delete(0,3);
//删除指定位置
sb.deleteCharAt(1);
System.out.println(sb);
//从0开始插入
sb.insert(0,"asd");
System.out.println(sb);
//[0,3)用*替换
sb.replace(0,3,"*");
System.out.println(sb);
//反转
sb.reverse();
System.out.println(sb);
StringBuffer类
用于表示可变字符串的一个类,是线程安全的,建议在多线程环境下使用,效率略低于StringBuilder。
StringBuilder和StringBuffer中的方法作用都一致,只不过StringBuffer中的方法使用了synchronized关
键字修饰,表示一个同步方法,在多线程环境下不会出现问题。
StringBuilder是一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。
StringBuiffer也代表可变字符串对象。实际上,StringBuilder和StringBuffer基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。
包装类
八个基本数据类型都有包装类
装箱
概念:所有包装类都有一个静态方法valueOf(原始类型),将某个原始类型的数据转换为相应的包装类对象,这个过程称为装箱。
//手动装箱
int i=123;//定义一个原始类型的数据
Integer aInteger=Integer.valueOf(i);//调用包装类的valueOf()方法将原始类型转换为包 装类对象
拆箱
概念:
所有包装类都有一个原始类型Value()方法,用于将包装类对象转换为原始类型,这个过程称为拆箱
//手动拆箱
Integer aInteger=new Integer(123);//创建一个包装类对象
int i = aInteger.intValue();//调用包装类的"原始类型Value()"方法将其转换为原始类型
//自动装箱
Integer aInteger=123;
//自动拆箱
int i=aInteger;
自动装箱池
//以下代码的输出结果:
Integer i1=new Integer(100);
Integer i2=new Integer(100);
//i3中保存的100,在byte范围内,保存在"自动装箱池"中
Integer i3=100;
//i4中保存的100,在byte范围内,如果有现成的,直接引用
Integer i4=100;
//i5和i6中保存的200,超出byte范围,会创建两个新对象
Integer i5=200;
Integer i6=200;
System.out.println(i1==i2);//false
//i3和i4保存的是同一个地址,所以是true
System.out.println(i3==i4);//true
//i5和i6保存的是两个地址,所以是false
System.out.println(i5==i6);//false
//涉及包装类的比较,要使用包装类重写了的equals方法
System.out.println(i5.equals(i6));
如果通过调用构造方法创建的包装类对象,属于不同地址,使用==比较的结果为false
自动装箱的形式,赋值范围在-128~127之间,将这个范围内的数保存到了"自动装箱池"中,
所以两个包装类对象保存的数在这个范围内时,使用同一个地址。超过这个范围,使用的不是同一个地址。
所以我们在引用类型之间比较,一定不要使用**==,要使用重写的equals**方法
习题
输入一段字符串,拼接n次,统计每个字符出现的次数
解法一(不能统计中文):
Scanner sc = new Scanner(System.in);
System.out.println("输入一段英文字符:");
String str = sc.next();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 20; i++) {
sb.append(str);
}
char[] chars = sb.toString().toCharArray();
int[] list = new int[123];
for (int i = 0; i < chars.length; i++) {
//char[0]: a
//chars[i]是每个字母对应的ascii码,即是list[a]--list[97]
list[chars[i]]++;
}
for (int i = 65; i < list.length; i++) {
if (list[i] != 0){
System.out.println((char)i+":"+list[i]);
}
}
解法二:
Scanner sc = new Scanner(System.in);
System.out.println("输入一段英文字符:");
String str = sc.next();
//定义一个字符数组存储字符串出现的单词
char[] letters = new char[100];
for (int i = 0;i < str.length();i++){
//取出字符串每一位
letters[i] = str.charAt(i);
//循环判断新添加的一位和前面的是否重复
for (int j = 0;j < i;j++){
//重复让它为0
if (letters[i] == letters[j]) {
letters[i] = 0;
break;
}
}
}
// for (char l : letters) {
// if (l != 0){
// System.out.println(l);
// }
// }
StringBuilder sb = new StringBuilder();
System.out.println("输入拼接次数");
int n = sc.nextInt();
//将前面的字符串拼接
for (int i = 0; i < n; i++) {
sb.append(str);
}
//StringBuilder转化为字符串
String str1 = sb.toString();
//字符串转化为字符数组
char[] str2 = str1.toCharArray();
//将前面提取出来的每个字母循环和拼接后的进行比较
for (char letter : letters) {
if (letter != 0) {
int count = 0;
for (char c : str2) {
if (letter == c) {
count++;
}
}
System.out.println(letter + ": " + count + "次");
}
}
边栏推荐
- MongoDB数据接入实践
- Modulo operation (MOD)
- typescript56 - generic interface
- 2022 China Computing Power Conference released the excellent results of "Innovation Pioneer"
- Linux安装mysql最简单教程(一次成功)
- typescript52-简化泛型函数调用
- 阿里云技术专家邓青琳:云上跨可用区容灾和异地多活最佳实践
- 114. How to find the cause of Fiori Launchpad routing error by single-step debugging
- 研究生新生培训第四周:MobileNetV1, V2, V3
- 【QT小记】QT中信号和槽的基本使用
猜你喜欢
随机推荐
typescript53-泛型约束
C语言:学生管理系统(链表版)
Analysis: What makes the Nomad Bridge hack unique
Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
如何用C语言代码实现商品管理系统开发
虚拟机CentOS7中无图形界面安装Oracle
特征值与特征向量
Analysis of usage scenarios of mutex, read-write lock, spin lock, and atomic operation instructions xaddl and cmpxchg
boot issue
typescript55-泛型约束
114. 如何通过单步调试的方式找到引起 Fiori Launchpad 路由错误的原因
XSS - Bypass for loop filtering
Tanabata festival coming, VR panoramic look god assists for you
观察者模式
typescript56 - generic interface
boot issue
分析:Nomad Bridge黑客攻击的独特之处
GNSS【0】- 专题
敏捷交付的工程效能治理
nodejs切换版本使用(不需要卸载重装)