Java8关于BigDecimal的求和,求平均,最⼩,最⼤,⽀持分组
前⾔:
java8的label表达式功能⾮常强⼤,精简代码,提⾼代码效率⾮常有效,尤其是对集合上的⽀持可谓空前强⼤,⽐如分组求和,最⼤,筛选,排序,不过这些⽀持⼀般是针对普通数据类型的,但是项⽬当中很多时候考虑到⼩数精度问题会抛弃Double数据类型,⽽采⽤BigDecimal,虽然java8也⽀持BigDecimal的求和,平均等等,不过写法⾮常⿇烦,花了半天时间研究其源码,并且对其进⾏改写,基本上符合⼤部分业务场景。废话不多说,直接上代码,转载请标明连接出处。
定义接⼝
import java.math.BigDecimal;
@FunctionalInterface
public interface ToBigDecimalFunction <T>{
BigDecimal applyAsBigDecimal(T value);
}
编写⾃定义的Collectors
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Collections;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
/**
*
* @author chen.kai
* 2019年12⽉14⽇
* <p>
* 因java8没有关于Bigdecimal求和的⼀类⽅法,这⾥根据java8包含的int,double求和的⽅法,进⾏修改,变为⾃⼰合适的⽅法
* </p>
*/
public final class CustomCollectors {
private static final Set<Collector.Characteristics> CH_NOID = ptySet();
private CustomCollectors(){}
@SuppressWarnings("unchecked")
private static <I, R> Function<I, R> castingIdentity(){
return i ->(R) i;
}
/**
* Simple implementation class for{@code Collector}.
*
* @param <T> the type of elements to be collected
* @param <R> the type of the result
*/
@SuppressWarnings("hiding")
static class CollectorImpl<T, A, R> implements Collector<T, A, R>{
private final Supplier<A> supplier;
private final BiConsumer<A, T> accumulator;
private final BinaryOperator<A> combiner;
private final BinaryOperator<A> combiner;
private final Function<A, R> finisher;
private final Set<Characteristics> characteristics;
CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Function<A,R> finisher,
Set<Characteristics> characteristics){
this.supplier = supplier;
this.accumulator = accumulator;
thisbiner = combiner;
this.finisher = finisher;
this.characteristics = characteristics;
}
CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Set<Characteristics> characteristics){
this(supplier, accumulator, combiner, castingIdentity(), characteristics);
java stream}
@Override
public BiConsumer<A, T> accumulator(){
return accumulator;
}
@Override
public Supplier<A> supplier(){
return supplier;
}
@Override
public BinaryOperator<A> combiner(){
return combiner;
}
@Override
public Function<A, R> finisher(){
return finisher;
}
@Override
public Set<Characteristics> characteristics(){
return characteristics;
}
}
/
/求和⽅法
public static <T> Collector<T, ?, BigDecimal> summingBigDecimal(ToBigDecimalFunction<? super T> mapper){
return new CollectorImpl<>(
() -> new BigDecimal[]{new BigDecimal(0)},
(a, t) ->{ a[0]= a[0].add(mapper.applyAsBigDecimal(t), MathContext.DECIMAL32);},
(a, b) ->{ a[0]= a[0].add(b[0], MathContext.DECIMAL32);return a;},
a -> a[0], CH_NOID);
}
//求最⼤,这⾥的最⼩MIN值,作为初始条件判断值,如果某些数据范围超过百亿以后,可以根据需求换成Long.MIN_VALUE或者Double.MIN_VALUE public static <T> Collector<T, ?, BigDecimal> maxBy(ToBigDecimalFunction<? super T> mapper){
return new CollectorImpl<>(
() -> new BigDecimal[]{new BigDecimal(Integer.MIN_VALUE)},
(a, t) ->{ a[0]= a[0].max(mapper.applyAsBigDecimal(t));},
(a, b) ->{ a[0]= a[0].max(b[0]);return a;},
a -> a[0], CH_NOID);
a -> a[0], CH_NOID);
}
//求最⼩,这⾥的最⼤MAX值,作为初始条件判断值,如果某些数据范围超过百亿以后,可以根据需求换成Long.MAX_VALUE或者Double.MAX_VALUE public static <T> Collector<T, ?, BigDecimal> minBy(ToBigDecimalFunction<? super T> mapper){
return new CollectorImpl<>(
() -> new BigDecimal[]{new BigDecimal(Integer.MAX_VALUE)},
(a, t) ->{ a[0]= a[0].min(mapper.applyAsBigDecimal(t));},
(a, b) ->{ a[0]= a[0].min(b[0]);return a;},
a -> a[0], CH_NOID);
}
/**
* 返回⼀个平均值
* @param newScale 保留⼩数位数
* @param roundingMode ⼩数处理⽅式
* #ROUND_UP 进1
* #ROUND_DOWN 退1
* #ROUND_CEILING 进1截取:正数则ROUND_UP,负数则ROUND_DOWN
* #ROUND_FLOOR 退1截取:正数则ROUND_DOWN,负数则ROUND_UP
* #ROUND_HALF_UP >=0.5进1
* #ROUND_HALF_DOWN >0.5进1
* #ROUND_HALF_EVEN
* #ROUND_UNNECESSARY
*/
//求平均,并且保留⼩数
public static <T> Collector<T, ?, BigDecimal> averagingBigDecimal(ToBigDecimalFunction<? super T> mapper, int newScale, int roundingMode){ return new CollectorImpl<>(
() -> new BigDecimal[]{new BigDecimal(0),new BigDecimal(0)},
(a, t) ->{ a[0]= a[0].add(mapper.applyAsBigDecimal(t)); a[1]= a[1].add(BigDecimal.ONE);},
(a, b) ->{ a[0]= a[0].add(b[0]);return a;},
a -> a[0].divide(a[1],MathContext.DECIMAL32).setScale(newScale,roundingMode), CH_NOID);
}
}
测试:
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import util.CustomCollectors;
/**
* @author chen.kai
* @date 2019年12⽉14⽇
* @description
*/
public class Test2 {
public static void main(String[] args){
//测试数据主备
List<Student> list = new ArrayList<Student>();
list.add(new Student(1, "张三", new BigDecimal(-1)));
list.add(new Student(1, "张三", new BigDecimal(180.5)));
list.add(new Student(1, "张三", new BigDecimal(170.6)));
list.add(new Student(2, "李四", new BigDecimal(160)));
Map<Integer, BigDecimal> map = list.stream().collect(
System.out.println("求和的数据" + String());
System.out.println("=======================================");
Map<Integer, BigDecimal> map1 = list.stream().collect(
System.out.println("----------------------------------------");
Map<Integer, BigDecimal> map2 = list.stream().collect(
/
/ System.out.println(new BigDecimal(170.11).add(new BigDecimal(1), MathContext.DECIMAL32));
System.out.println("求最⼤的值为:" +String());
System.out.println("----------------------------------------");
Map<Integer, BigDecimal> map3 = list.stream().collect(
System.out.println("分组后的最⼩值为:" + String());
}
static class Student {
private Integer id;
private String name;
private BigDecimal height;
public Student(){}
/**
* @param id
* @param name
* @param height
*/
public Student(Integer id, String name, BigDecimal height){
super();
this.id =id;
this.name = name;
this.height = height;
}
/**
* @return the id
*/
public Integer getId(){
return id;
}
/**
* @param id the id to set
*/
public void setId(Integer id){
this.id =id;
}
/**
* @return the name
*/
public String getName(){
return name;
}
/**
* @param name the name to set
*/
public void setName(String name){
this.name = name;
}
/**
* @return the height
*/
public BigDecimal getHeight(){
return height;
}
/**
* @param height the height to set
*/
public void setHeight(BigDecimal height){
this.height = height;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString(){
return"Student [id=" + id + ", name=" + name + ", height=" + height + "]";
}
}
}
测试结果,求平均⽀持四舍五⼊,直接截取等等⼩数保留位算法:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论