java知识点:BigDecimal:金额相关以及compareto比较

BigDecimal:金额相关

BigDecimal 是java小数操作的一个专有类,在电商、金融行业 存储跟金额有关的字段

Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算,双精度浮点型变量double可以处理16位有效数。不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度,在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象

     BigDecimal a = new BigDecimal(5);
     BigDecimal b = new BigDecimal(40);
     BigDecimal add = a.add(b); // +
     BigDecimal subtract = a.subtract(b); // -
     BigDecimal multiply = a.multiply(b); // *

     BigDecimal divide = a.divide(b); // \
     BigDecimal result5 = num2.divide(num1, 20, BigDecimal.ROUND_HALF_UP)//后面说明
     第二个参数为保留几位小数,➗务必写成这种,防止异常java.lang.ArithmeticException

     BigDecimal result4 = num3.abs(); //绝对值
        
注意:  System.out.println()中的数字默认是double类型的,double类型小数计算不精准。
        使用BigDecimal类构造方法传入double类型时,计算的结果也是不精确的!


取整:
BigDecimal bd = new BigDecimal("12.1");
long l  = bd.setScale( 0, BigDecimal.ROUND_UP ).longValue(); // 向上取整
long l  = bd.setScale( 0, BigDecimal.ROUND_DOWN ).longValue(); // 向下取整

BigDecimal b = new BigDecimal("2.225667").setScale(2, BigDecimal.ROUND_DOWN);
//b = 2.22 直接去掉多余的位数

BigDecimal c = new BigDecimal("2.224667").setScale(2, BigDecimal.ROUND_UP);
//c = 2.23 跟上面相反,进位处理

因为不是所有的浮点数都能够被精确的表示成一个double 类型值,有些浮点数值不能够被精确的表示成 double 类型值,因此它会被表示成与它最接近的 double 类型的值。必须改用传入String的构造方法。这一点在BigDecimal类的构造方法注释中有说明

//尽量用字符串的形式初始化
    BigDecimal num12 = new BigDecimal("0.005");
    BigDecimal num12 = new BigDecimal(Double.toString(d));
    BigDecimal num12 = BigDecimal.valueOf(1.010);
    // 使用string类型额构造函数进行构造时,equals无法比较,比如多余的0
    // compareTo方法则只会进行大小的比较,与精度无关:1.010=1.01为true

     compareTo返回为正数表示a1>a2, 返回为负数表示a1
    //        c=1.010 ,b=1.01, c.compareTo(b) = 0  //b c 都是BigDecimal类型
    // 使用valueof方法进行构造时,他会帮我们去掉多余的精度可以用equals比较
    //        c.equals(b)  = true

BigDecimal 精度描述:

模式               描述
CEILING        正无穷大方向取整
FLOOR          负无穷大方向取整
DOWN           向 0 的方向取整
UP                 正数向正无穷大取整,负数向负无穷大取整
HALF_UP          5,6,7,8,9 向上取整、 1,2,3,4 向下取整、 常用的4舍5入
HALF_DOWN    6,7,8,9 向上取整 1,2,3,4,5 向下取整
HALF_EVEN     小数位是5时,判断整数部分是奇数就进位、 小数位是5时,判断整数部分是偶数就舍弃、
                           1,2,3,4, 舍弃、 6,7,8,9, 进位


常用方法PS
currency = NumberFormat.getCurrencyInstance();    //建立货币格式化引用
NumberFormat percent = NumberFormat.getPercentInstance();     //建立百分比格式化用
percent.setMaximumFractionDigits(3);               //百分比小数点最多3位

currency.format(bigLoanAmount)
percent.format(bigInterestRate)
currency.format(bigInterest)

BigDecimal数字数据转String文本

直接返回给前端的话11.00会显示为11,

// 浮点数的打印
System.out.println(new BigDecimal("10000000000").toString());

// 普通的数字字符串
System.out.println(new BigDecimal("100.000").toString());

// 去除末尾多余的0
System.out.println(new BigDecimal("100.000").stripTrailingZeros().toString());

// 避免输出科学计数法
System.out.println(new BigDecimal("100.000").toPlainString());

// 四舍五入,保留两位小数,避免输出科学计数法
System.out.println(new BigDecimal("100.000").setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());

附 java中的compareto方法

返回为正数表示a1>a2, 返回为负数表示a1

除了基本类型(< = >);Date、String、Integer、或者其他的,可以直接使用compareTo比较

  • 返回参与比较的前后两个字符串的asc码的差值,如果两个字符串首字母不同,则该方法返回首字母的asc码的差值

 

String a1 = "a";
String a2 = "c";
System.out.println(a1.compareTo(a2));//结果为-2
  • 参与比较的两个字符串如果首字符相同,则比较下一个字符,直到有不同的为止,返回该不同的字符的asc码差值

 

String a1 = "aa";
String a2 = "ad";
System.out.println(a1.compareTo(a2));//结果为-3
  • 如果两个字符串不一样长,可以参与比较的字符又完全一样,则返回两个字符串的长度差值

 

String a1 = "aa";
String a2 = "aa12345678";
System.out.println(a1.compareTo(a2));//结果为-8
  • compareToIgnoreCase忽略大小写
  • Comparable接口中的compareTo
compareTo方法内必须做非空判断(规范问题),当然int类型就不用了。
1、模型必须实现Comparable接口
2、Collection.sort(list)会自动调用compareTo,如果没有这句,list是不会排序的,也不会调用compareTo方法
3、如果是数组则用Arrays.sort(a)方法

// 实体类重写
@Override
public int compareTo(Book o) {
    // TODO Auto-generated method stub
    //return this.bookPrice-o.bookPrice;//按价格排序 升序
    //return o.bookPrice-this.bookPrice;//按价格排序 降序
    //return this.bookName.compareTo(o.bookName);//按书名排序 升序
    //先按 id 再按价格 最后按书名排序 升序
    int result = this.bookId - o.bookId;
    if(result == 0){
        result =this.bookPrice - o.bookPrice;
    }
    if(result == 0){
        result = this.bookName.compareTo(o.bookName);
    }
    return result;
}
// 使用
Collections.sort(books);

list排序

// JDK1.8以前的老用法,之前一直这样写
Collections.sort(books,new Comparator() {

            @Override
            public int compare(Book o1, Book o2) {
                // TODO Auto-generated method stub
                
                return o1.getBookPrice() - o2.getBookPrice();
                
            }
        });

// JDK1.8
Collections.sort(books,(Book a, Book b) -> { return a.getBookPrice()-b.getBookPrice(); });

// 简写1
Collections.sort(books,(Book a, Book b) ->  a.getBookPrice()-b.getBookPrice());
// 简写2
Collections.sort(list, Comparator.comparingInt(Channel::getChnumber));

treeMap 中(基于key的排序)

treeMap默认的是基于key的从小到大 的排列
自定义排序也是基于key的,如果key object类型 可以自定义各种排序

TreeMap treeMap = new TreeMap<>((String a,String b)-> b.compareTo(a));//降序
TreeMap treeMap = new TreeMap<>((String a,String b)-> a.compareTo(b));//升序

TreeMap的按value排序

(转换成entry list 然后排序)汉字是按ascii码排序的,不是汉语拼音

User p1 = new User(1, "A小红");
User p2 = new User(5, "D赵明");
User p3 = new User(2, "W孙宇");
User p4 = new User(9, "C黎明");

TreeMap treeMap = new TreeMap<>();

treeMap.put("45", p1);
treeMap.put("12", p2);
treeMap.put("85", p3);
treeMap.put("33", p4);


List> entries = new ArrayList<>(treeMap.entrySet());

Collections.sort(entries,
        (Map.Entry e1, Map.Entry e2) -> ((User) e1.getValue()).getUserName()
                .compareTo(((User) e2.getValue()).getUserName()));
System.out.println("按名字顺序排列");
for (Entry entry : entries) {
    System.out.println(entry.getValue());

}

更多java常用知识点整理:https://blog.csdn.net/qq_44695727/article/details/101054712

你可能感兴趣的:(java,学习与记录,java)