创建 BigDecimal 列表的对象绑定以获取总计

tri*_*ogy 2 java javafx

LineItem我正在尝试使用以下行创建金额列表的绑定:

ReadOnlyObjectWrapper<BigDecimal> total = new ReadOnlyObjectWrapper<>();

total.bind(Bindings.createObjectBinding(() -> items.stream()
                        .collect(Collectors.summingDouble(LineItem::getTotal)),
                        items));
Run Code Online (Sandbox Code Playgroud)

显然,它Collectors.summingDouble不会工作,因为它是BigDecimal. 有没有办法用 BigDecimal 来做到这一点?

LineItem.java

public class LineItem
{
        private final SimpleObjectProperty<BigDecimal> amount;
        
        public LineItem()
        {
            this.amount = new SimpleObjectProperty<>();
        }
        
        public BigDecimal getTotal()
        {
            return this.amount.get();
        }
        
}
    
Run Code Online (Sandbox Code Playgroud)

理想情况下,属性的更改将反映在总属性中......

Jam*_*s_D 5

为了使这项工作有效,需要进行一些更改:

  1. 您需要在LineItem类中定义一个“属性访问器”方法,以访问实际的ObjectProperty<BigDecimal>(而不仅仅是BigDecimal它包装的)。这允许列表在个别金额发生变化时发送通知。
  2. 您需要ObservableList使用“提取器”创建您的绑定,以便在单个金额属性发生变化时它可以向您的绑定发送更新通知
  3. 修复绑定中的函数以对实例求和,如本问题BigDecimal所述

这看起来像:

public class LineItem {
    private final SimpleObjectProperty<BigDecimal> amount;
    
    public LineItem()
    {
        this.amount = new SimpleObjectProperty<>();
    }
    
    public final BigDecimal getTotal()
    {
        return this.amount.get();
    }

    public ObjectProperty<BigDecimal> totalProperty() {
        return amount ;
    }

    public final void setTotal(BigDecimal total) {
        totalProperty().set(total);
    }
    
}
Run Code Online (Sandbox Code Playgroud)

然后

ObservableList<LineItem> items = FXCollections.observableArrayList(
    item -> new Observable[] {item.totalProperty()}
);
Run Code Online (Sandbox Code Playgroud)

total.bind(Bindings.createObjectBinding(() -> items.stream()
         .map(LineItem::getTotal)
         .reduce(BigDecimal.ZERO, BigDecimal::add),
     items));
Run Code Online (Sandbox Code Playgroud)