当前位置:网站首页>可变字符串
可变字符串
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 + "次");
}
}
边栏推荐
- Vant3 - click on the corresponding name name to jump to the next page corresponding to the location of the name of the TAB bar
- JS 保姆级贴心,从零教你手写实现一个防抖debounce方法
- js函数防抖和函数节流及其使用场景
- 即席查询——Presto
- Flink jdbc connector 源码改造sink之 clickhouse多节点轮询写与性能分析
- C # WPF equipment monitoring software (classic) - the next
- outputBufferIndex = mDecode.dequeueOutputBuffer(bufferInfo, 0) 一直返回为-1
- typescript54-泛型约束
- 一篇文章看懂JS闭包,从执行上下文角度解析有趣的闭包
- 【链路聚合原理及配置】
猜你喜欢
随机推荐
Electronics manufacturing enterprise deployment WMS what are the benefits of warehouse management system
循环绕过问题
字符串的排列
thinkphp 常用技巧
多渠道打包
splice随机添加和删除的写法
2022 China Computing Power Conference released the excellent results of "Innovation Pioneer"
Google Earth Engine - Calculates the effective width of rivers using publicly available river data
LeetCode第三题(Longest Substring Without Repeating Characters)三部曲之三:两次优化
互斥锁、读写锁、自旋锁,以及原子操作指令xaddl、cmpxchg的使用场景剖析
nodejs 安装多版本 版本切换
【无标题】
nodejs+npm的安装与配置
【链路聚合原理及配置】
GNSS文章汇总
网络带宽监控,带宽监控工具哪个好
静态文件快速建站
Array_Sliding window | leecode brushing notes
Web3 security risks daunting?How should we respond?
电子制造企业部署WMS仓储管理系统的好处是什么









