前言
今天在练习代码优化的时候遇到了replaceAll这个方法,觉得这个方法很有意义,就研究了一下它,复习了一下Math和常用数据类型的一些用法,挺有收获的。
代码
package test.CollectionAndMap.Collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
*
* 源码:
* 接口:interface UnaryOperator<T> extends Function<T, T>
* UnaryOperator 一元运算符,就是对每个符合条件值进行对应处理 格式为 list.replaceAll(x -> 对x的处理),
* 因为List中元素类型要求一致,所以这里关于x的处理结果需要返回同类型
* 包装类,分别为Byte、Short、Integer、Long、Float、Double、Character、Boolean
*
*/
public class ListReplaceAll {
public static void main(String[] args) {
// 1.Integer
List<Integer> listInteger1 = new ArrayList<>();
listInteger1.add(6);
listInteger1.add(-2);
listInteger1.add(3);
listInteger1.add(16);
// listInteger1 -> [6, -2, 3, 16] System.out.println(Arrays.toString(listInteger1.toArray()));
// 加法运算
listInteger1.replaceAll(x -> x+2); // [8, 0, 5, 18]
// 减法运算
listInteger1.replaceAll(x -> x-2); // [6, -2, 3, 16]
// 自增,测试后发现x++ 无效 listInteger1.replaceAll(x -> ++x); // [7, -1, 4, 17]
// 自减,测试后发现x-- 无效
listInteger1.replaceAll(x -> --x); // [6, -2, 3, 16]
// 乘法运算
listInteger1.replaceAll(x -> x*3); // [18, -6, 9, 48]
// 除法运算
listInteger1.replaceAll(x -> x/2); // [9, -3, 4, 24]
// 取余
listInteger1.replaceAll(x -> x%2); // [1, -1, 0, 0]
// 位非运算符(~):正数取反、-1;负数取反、+1
listInteger1.replaceAll(x -> ~x); // [-2, 0, -1, -1]
// 其他数学计算 max
listInteger1.replaceAll(x -> Math.max(x,-1)); // [-1, 0, -1, -1]
listInteger1.replaceAll(x -> Math.addExact(x,-1)); // [-2, -1, -2, -2]
List<Integer> listInteger2 = new ArrayList<>();
listInteger2.add(86520803);
listInteger2.add(0);
listInteger2.add(38);
listInteger2.add(-11);
// listInteger2 -> [86520803, 0, 38, -11]
// min
listInteger2.replaceAll(x -> Math.min(x,3)); // [3, 0, 3, -11]
// multiplyExact 用于计算两个整数的积,如果积超出了int或long的范围抛出ArithmeticException异常
listInteger2.replaceAll(x -> Math.multiplyExact(x,9)); // [27, 0, 27, -99]
// 计算乘积,由于listInteger1 是Integer的,这里需要Math.toIntExact
// since 9 , Math.toIntExact(Math.multiplyFull(x, 999999999) 会报错:java.lang.ArithmeticException: integer overflow at java.base/java.lang.Math.toIntExact(Math.java:1071)
listInteger2.replaceAll(x -> Math.toIntExact(Math.multiplyFull(x, 2))); // [54, 0, 54, -198]
List<Integer> listInteger3 = new ArrayList<>();
listInteger3.add(10);
listInteger3.add(799);
listInteger3.add(-5);
listInteger3.add(-1029385637);
// listInteger3 -> [10, 799, -5, -1029385637]
// 相反数
listInteger3.replaceAll(x -> Math.negateExact(x)); // [-10, -799, 5, 1029385637]
// subtractExact返回x-2的值,如果结果溢出了long则抛出异常
listInteger3.replaceAll(x -> Math.subtractExact(x,2)); // [-12, -801, 3, 1029385635]
// floorDiv 除法结果向下取整
listInteger3.replaceAll(x -> Math.floorDiv(x,3)); // [-4, -267, 1, 343128545]
// Double
List<Double> listDouble1 = new ArrayList<>();
listDouble1.add(91.2);
listDouble1.add(22.3);
listDouble1.add(34.7);
listDouble1.add(2.2);
listDouble1.add(55.9);
// listDouble1 -> [91.2, 22.3, 34.7, 2.2, 55.9]
// 向下舍入整数
listDouble1.replaceAll(x -> Double.valueOf(Math.round(x))); // [91.0, 22.0, 35.0, 2.0, 56.0]
// 向上舍入整数
listDouble1.replaceAll(x -> Math.ceil(x)); // [91.0, 22.0, 35.0, 2.0, 56.0]
// 绝对值
listDouble1.replaceAll(x -> Math.abs(x)); // [91.0, 22.0, 35.0, 2.0, 56.0]
// 舍去小数位
listDouble1.replaceAll(x -> Math.floor(x)); // [91.0, 22.0, 35.0, 2.0, 56.0]
// since 9,最接近乘积的double值
listDouble1.replaceAll(x -> Math.fma(x,52,85)); // [4817.0, 1229.0, 1905.0, 189.0, 2997.0]
// 下面关于 % 和 IEEEremainder 的区别参考自:https://blog.csdn.net/slobe/article/details/6397885
/**
* 以下会出现 NaN -Infinity 的结果
*/
// 余数,IEEERemainder = dividend - (divisor * Math.Round(dividend / divisor))
listDouble1.replaceAll(x -> Math.IEEEremainder(x,2)); // [1.0, 1.0, 1.0, 1.0, 1.0]; x=0 会出现 -Infinity
// Modulus = (Math.Abs(dividend) - (Math.Abs(divisor) * (Math.Floor(Math.Abs(dividend) / Math.Abs(divisor))))) * Math.Sign(dividend)
listDouble1.replaceAll(x -> x%3);// [1.0, 1.0, 1.0, 1.0, 1.0]
List<Double> listDouble2 = new ArrayList<>();
listDouble2.add(3.14);
listDouble2.add(31.4);
listDouble2.add(62.8);
listDouble2.add(11.5);
listDouble2.add(56.3);
// listDouble2 -> [3.14, 31.4, 62.8, 11.5, 56.3]
// log 以e为底的对数
listDouble2.replaceAll(x -> Math.log(x+5)); // [2.096790180014449, 3.594568774642695, 4.216562194946349, 2.803360380906535, 4.115779842942166]
// log1p 以1为底的对数
listDouble2.replaceAll(x -> Math.log1p(x)); // [1.130366149265698, 1.5248749047536572, 1.6518386015896627, 1.3358849867248124, 1.6323298497457235]
// log10 以10为底的对数
listDouble2.replaceAll(x -> Math.log10(x)); // [0.053219143349313644, 0.1832342171886525, 0.21796761086372685, 0.12576906908195992, 0.21280792246304991]
// max min multiplyExact abs addExact 等与整型用法一致,不再赘述
// nextAfter 与第一个参数最接近的可够和第一个参数所拥有的位数一样的浮点数,方向根据第二个参数判断
listDouble2.replaceAll(x -> Math.nextAfter(x,0));// [0.05321914334931364, 0.18323421718865246, 0.21796761086372682, 0.1257690690819599, 0.2128079224630499]
// 向上接近
listDouble2.replaceAll(x -> Math.nextUp(x));// [0.053219143349313644, 0.1832342171886525, 0.21796761086372685, 0.12576906908195992, 0.21280792246304991]
// 向下最接近的值
listDouble2.replaceAll(x -> Math.nextDown(x)); // [0.05321914334931364, 0.18323421718865246, 0.21796761086372682, 0.1257690690819599, 0.2128079224630499]
// 幂
listDouble2.replaceAll(x -> Math.pow(x,3)); // [1.5073136731416425E-4, 0.006152048228013573, 0.010355614902112002, 0.0019893973683158574, 0.009637477470717413]
// 随机数
listDouble2.replaceAll(x -> Math.random());// [0.7722110690293934, 0.8370858901472782, 0.33050440781899926, 0.2576742763597336, 0.6627502490909225]
List<Double> listDouble3 = new ArrayList<>();
listDouble3.add(3.14);
listDouble3.add(31.4);
listDouble3.add(62.8);
listDouble3.add(11.5);
listDouble3.add(56.3);
// 四舍五入
listDouble3.replaceAll(x -> Math.rint(x));// [3.0, 31.0, 63.0, 12.0, 56.0]
// 精度
listDouble3.replaceAll(x -> Math.scalb(x,2));// [12.0, 124.0, 252.0, 48.0, 224.0]
// 判断一个数字是正数 1 、负数 -1 还是零 0
listDouble3.replaceAll(x -> Math.signum(x)); // [1.0, 1.0, 1.0, 1.0, 1.0]
// 正弦 sin
listDouble3.replaceAll(x -> Math.sin(x)); // [0.8414709848078965, 0.8414709848078965, 0.8414709848078965, 0.8414709848078965, 0.8414709848078965]
// 双曲正弦
listDouble3.replaceAll(x -> Math.sinh(x)); // [0.9443504370351303, 0.9443504370351303, 0.9443504370351303, 0.9443504370351303, 0.9443504370351303]
// 余弦 cos
listDouble3.replaceAll(x -> Math.cos(x)); // [0.5862692242006904, 0.5862692242006904, 0.5862692242006904, 0.5862692242006904, 0.5862692242006904]
// 双曲余弦
listDouble3.replaceAll(x -> Math.cosh(x)); // [1.1768349480813867, 1.1768349480813867, 1.1768349480813867, 1.1768349480813867, 1.1768349480813867]
// 这里我写的例子不太合适,所以出现了NaN,如有兴趣,您可以自己写一些相对合适一些的值
// 反余弦
listDouble3.replaceAll(x -> Math.acos(x)); // [NaN, NaN, NaN, NaN, NaN]
// 正切 tan
listDouble3.replaceAll(x -> Math.tan(x));// [NaN, NaN, NaN, NaN, NaN]
// 双曲正切
listDouble3.replaceAll(x -> Math.tanh(x));// [NaN, NaN, NaN, NaN, NaN]
// e的x次幂
listDouble3.replaceAll(x -> Math.exp(x));// [NaN, NaN, NaN, NaN, NaN]
// e的x次幂 减1
listDouble3.replaceAll(x -> Math.expm1(x));// [NaN, NaN, NaN, NaN, NaN]
// 弧度转度
listDouble3.replaceAll(x -> Math.toDegrees(x));// [NaN, NaN, NaN, NaN, NaN]
// 角度转弧度
listDouble3.replaceAll(x -> Math.toRadians(x));// [NaN, NaN, NaN, NaN, NaN]
// 最接近的浮点值
List<Double> listDouble4 = new ArrayList<>();
listDouble4.add(1.0);
listDouble4.add(-3.0);
listDouble4.add(2.0);
// listDouble4 ->[1.0, -3.0, 2.0]
listDouble4.replaceAll(x -> Math.ulp(x)); // [2.220446049250313E-16, 4.440892098500626E-16, 4.440892098500626E-16]
// 开方
listDouble4.replaceAll(x -> Math.sqrt(x)); // [1.4901161193847656E-8, 2.1073424255447017E-8, 2.1073424255447017E-8]
List<Long> listLong1 = new ArrayList<>();
listLong1.add(1L);
listLong1.add(2L);
listLong1.add(-3L);
listLong1.add(7L);
// listLong1 -> [1.4901161193847656E-8, 2.1073424255447017E-8, 2.1073424255447017E-8]
// floorMod(long x, long y) = x - floorDiv(x, y) * y;
listLong1.replaceAll(x -> Math.floorMod(x,2L)); // [1, 0, 1, 1]
List<String> listStr1 = new ArrayList<>();
listStr1.add("0000x1112039x");
listStr1.add("0000011120x94");
listStr1.add("000001x120394");
listStr1.add("00000111x0394");
listStr1.add("0x00011120x94");
// replaceAll 全部替换,replace 替换,replaceFirst 替换第一个,substring 截取
listStr1.replaceAll(x -> x.replace("x","X00X")); // [0000X00X1112039X00X, 0000011120X00X94, 000001X00X120394, 00000111X00X0394, 0X00X00011120X00X94]
listStr1.replaceAll(x -> x.replace("0","f")); // [ffffXffX1112f39XffX, fffff1112fXffX94, fffff1XffX12f394, fffff111XffXf394, fXffXfff1112fXffX94]
listStr1.replaceAll(x -> x.replaceFirst("1","8")); // [ffffXffX1112f39XffX, fffff1112fXffX94, fffff1XffX12f394, fffff111XffXf394, fXffXfff1112fXffX94]
listStr1.replaceAll(x -> x.substring(4,13)); // [XffX8112f, f8112fXff, f8XffX12f, f811XffXf, Xfff8112f]
listStr1.replaceAll(x -> x.substring(5)); // [112f, fXff, X12f, ffXf, 112f]
listStr1.replaceAll(x -> Arrays.toString(x.split("1"))); // [[, , 2f], [fXff], [X, 2f], [ffXf], [, , 2f]]
listStr1.replaceAll(x -> Arrays.toString(x.split("f", 2)));// [[[, , 2, ]], [[, Xff]], [[X, 2, ]], [[, fXf]], [[, , 2, ]]]
List<String> listStr2 = new ArrayList<>();
listStr2.add("2023-01-02 YYYY-MM-DD");
listStr2.add("2023-11-02 YYYY-MM-DD");
listStr2.add("2023-03-04 YYYY-MM-DD");
listStr2.add("2023-07-05 YYYY-MM-DD");
listStr2.add("2023-09-30 YYYY-MM-DD");
// 改为大写 toUpperCase 改为小写 toLowerCase
listStr2.replaceAll(String::toUpperCase);// x->x.toUpperCase() 的优化写法 [2023-01-02 YYYY-MM-DD, 2023-11-02 YYYY-MM-DD, 2023-03-04 YYYY-MM-DD, 2023-07-05 YYYY-MM-DD, 2023-09-30 YYYY-MM-DD]
listStr2.replaceAll(String::toLowerCase);// x->x.toLowerCase() 的优化写法 [2023-01-02 yyyy-mm-dd, 2023-11-02 yyyy-mm-dd, 2023-03-04 yyyy-mm-dd, 2023-07-05 yyyy-mm-dd, 2023-09-30 yyyy-mm-dd]
// getClass() 方法
listStr2.replaceAll(x-> String.valueOf(x.getClass()));// [class java.lang.String, class java.lang.String, class java.lang.String, class java.lang.String, class java.lang.String]
// Date 用于时间比较替换
List<Date> listDate1 = new ArrayList<>();
listDate1.add(new Date());
Date date = new Date(2230402854893L);
listDate1.replaceAll(x-> x.after(date) ? new Date() :date); // [Wed Sep 05 04:20:54 CST 2040]
listDate1.replaceAll(x-> x.before(date) ?date : new Date()); // [Fri Oct 20 17:19:21 CST 2023]
// Boolean
List<Boolean> listBoolean1 = new ArrayList<>();
listBoolean1.add(false);
listBoolean1.add(true);
// listBoolean1 -> [false, true]
listBoolean1.replaceAll(x -> x.booleanValue()); // 等同于 x-> x ;[false, true]
listBoolean1.replaceAll(x -> x.equals(false)); // 可以用来判断结果和预期结果是否一致 [true, false]
listBoolean1.replaceAll(x -> x.compareTo(false) < 0); // 对比,int值为 1 和 -1 时使用 [false, false]
// Character 和 Byte 没有 return 本身的方法或者属性,因此这里给出的是一些可能用到的处理方式
List<Character> listCharacter1 = new ArrayList<>();
listCharacter1.add('a');
listCharacter1.add('A');
listCharacter1.add('我');
// listByte1 -> [a, A, 我]
// 比较相对于某个char值得结果后进行处理
listCharacter1.replaceAll(x -> x.compareTo('a') > 0 ? 'b' : 'a'); // [a, a, b]
// Byte
List<Byte> listByte1 = new ArrayList<>();
listByte1.add((byte) 'a');
listByte1.add((byte) 'A');
listByte1.add((byte) '我');
// listByte1 -> [97, 65, 17]
listByte1.replaceAll(x -> x.doubleValue()>50?x : (byte) 'a'); // [97, 65, 97]
}
}
总结
List.replaceAll()方法中,参数取的是一元运算符,支持java 包装数据类型到同种类型之间的一些处理。