场景:想要将 ABCABB 的 A 替换为 B
一看到这个场景,我们首先想到的就是用 replace方法(会替换几个 A 呢?)
如果将所有的 A 都替换为 B,可以使用 replaceAll 方法(这个没有争议)
问题:replace
方法会替换几个 A 呢?
通过阅读源码,可以得知,replace方法会替换每一个匹配的字符串,那么它与 replaceAll 的区别在哪呢?
replace
,拥有两个重载的方法
字符 的替换
public String replace(char oldChar, char newChar) {}
"ABCABB".replace('A', 'B');
字符串 的替换
public String replace(CharSequence target, CharSequence replacement) {}
"ABCABB".replace("A", "B"); // 注意,用的是字符串
replaceAll
基于正则表达式 的替换(也可以用于普通字符串的替换)
public String replaceAll(String regex, String replacement) {}
// 普通字符串的替换
"ABCABB".replaceAll("A", "B");
// 正则表达式替换
"AB$C$ABB".replaceAll("\$", "B");
// 如果想直接写 $,可以用 replace
"AB$C$ABB".replace("$", "B");
问题:如果只想替换第一个匹配的字符串呢? ----- replaceFirst()
"ABCABB".replaceFirst("A", "B")
2. indexOf 的使用
场景:如果字符串中包含 $ 字符,那么就打印出一句话
这个场景,我们可以使用两种方式进行解决,既然题目为 indexOf 的使用,那么先看如何用 indexOf 实现
if ("123dj9ABC".indexOf("$") > -1) {
System.out.println("Hello world!")
}
一定要注意:if 语句中的条件,是 > -1
,不能写为 > 0 (如果想要查找的 $字符在第一位,那么就会返回 0,则虽然包含 $,但是条件不成立)
问题:更简单的方法?(底层还是 indexOf) ------ contains()
if ("123dj9ABC".contains("$")) {
System.out.println("Hello world!")
}
3. 数值包装类的相等问题
场景:判断两个 Integer 类型的数值是否相等
看到这个场景,如果代码中我们直接用 ==
进行判断,结果是 true 还是 false呢
false 的结果 ----- new Integer(1);
Integer num1 = new Integer(1);
Integer num2 = new Integer(1);
System.out.println(num1 == num2);
// 由于两个数是直接 new出来的,地址肯定不相同,所以直接使用 == ,返回 false
true 的结果 ----- Integer.valueOf(1);
Integer num1 = Integer.valueOf(1);
Integer num2 = Integer.valueOf(1);
System.out.println(num1 == num2);
// 通过阅读源码可以得知,使用 valueOf 方法时,数值在 -128 到 127范围内的值,是有缓存的,不会新 new一个
问题:涉及到数值类型的包装类如何进行相等判断?
解决
:应使用 equals
方法进行判断
Integer num1 = new Integer(1);
Integer num2 = new Integer(1);
System.out.println(num1.equals(num2)); // 结果为 true
4. 数值精度问题
场景:交易金额进行计算
涉及到金额的计算,我们一般需要将字段类型定义为 BigDecimal
,避免定义为 Double 类型时,精度丢失的问题
例如如下 *** 作:
double num1 = 0.03;
double num2 = 0.02;
System.out.println(num1 - num2); // 使用 0.02 - 0.01 却不会损失精度
得到的结果是: 0.009999999999999998,与预计的 0.01 不相符
----> Double 类型的两个参数相减,会先将数字转为 二进制 再进行运算,而 Double的有效位数为 16位
,所以可能会出现存储小数位数不够的情况,进而导致了误差的出现
问题:但是使用 BigDecimal 就一定能避免丢失精度嘛?
BigDecimal num1 = new BigDecimal(0.03);
BigDecimal num2 = new BigDecimal(0.02);
System.out.println(num1.subtract(num2));
得到的结果是:0.0099999999999999984734433411404097569175064563751220703125
通过阅读源码可知,构造方法的结果是不可预测的,例如想创建 0.1 的值,结果却是0.1000000000000000055511151231257827021181583404541015625的情况
解决
:因此官方更推荐我们使用 valueOf
的方式
BigDecimal num1 = BigDecimal.valueOf(0.03);
BigDecimal num2 = BigDecimal.valueOf(0.02);
System.out.println(num1.subtract(num2));
如果在 IDEA上安装了 Alibaba的代码检查插件,也可以看到对应提示
5. 字符串拼接问题场景:将两个字符串的值进行拼接
也许我们第一时间想到的就是用 “123” + “456” 的方式
但是 String 类型的字符串被称为不可变序列,也就是定义好之后,就不能被修改了(我们进行的修改,实际上是创建了新的对象)
可以看到底层使用的是 final 修饰的
问题:如何进行字符串的拼接呢?
使用可变字符序列 StringBuilder 和 StringBuffer,来定义对象
StringBuilder
(线程不安全,效率高)StringBuffer
(线程安全,效率低)
String a = "123";
StringBuilder builder = new StringBuilder();
builder.append(a).append("456");
System.out.println(builder);
问题:使用 + 拼接 String 类型的对象,效率一定比使用 append 拼接 StringBuilder 类型的对象低嘛?
public class StringDemo {
public static void main(String[] args) {
String a = "123";
String b = "456";
String c = a + b;
System.out.println(c);
}
}
通过使用 javap -c StringDemo.class
,可以发现,虽然代码中用的是 + *** 作,但是编译为字节码文件之后,实际上是被优化为了 StringBuilder 的 append *** 作(JDK1.5之后)
场景:判断前台传过来的字段值是否为空
我们一般常规的写法:
if (null != str && !"".equals(str)) {
System.out.println("not empty");
}
每次都这么判断太不优雅了,可以使用主流的工具类
apache common 3中的 StringUtils
类
注意:isEmpty 和 isBlank 方法的区别
StringUtils.isEmpty(" ") // false
StringUtils.isBlank(" ") // true
7. mapper 查询结果的判空
场景:处理查询出来的结果
List<Student> list = studMapper.getList(params);
for (Student stu : list) {
// todo
}
问题:这里是否要做判空处理,然后再进行 *** 作呢?
这里是不用进行判空
的,通过阅读源码可知,MyBatis 的查询方法最终都会调用到 org.apache.ibatis.executor.resultset 包下的 DefaultResultSetHandler类的 handleResultSets
方法,该方法会返回一个 multipleResultList 集合对象,而该对象在一开始就 new 出来了,肯定是不会空的,不会出现 NullPointerException
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)