You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改自定义java.util.Stack子类实现与JavaFX ListView/TableView的绑定

JavaFX自定义栈与ListView/TableView绑定的改造方案

你当前的ComplexNumberStack继承自JDK原生java.util.Stack,本身不具备变更通知能力,无法直接和JavaFX的列表控件实现数据绑定。我们需要通过引入JavaFX的可观察集合作为底层存储,让栈的所有修改操作自动触发变更事件,实现观察者模式的效果。

改造核心要点

  • 放弃继承JDK原生Stack类:JDK的Stack是基于Vector的遗留类,性能差且不可观察,改为内部持有ObservableList<ComplexNumber>作为底层存储,对外保留标准栈操作接口+自定义的getOperand方法
  • 所有修改操作直接作用于可观察集合:push、pop、批量操作的逻辑都基于内部ObservableList实现,修改时会自动触发变更通知,不需要手动实现观察者监听逻辑
  • 对外暴露只读可观察视图:避免外部直接修改内部数据破坏栈的后进先出结构,绑定控件时直接使用这个只读视图即可

改造后完整代码

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EmptyStackException;
import java.util.Iterator;
import java.util.List;

public class ComplexNumberStack {
    private static ComplexNumberStack instance = null;
    // 底层用ObservableList存储,支持变更通知
    private final ObservableList<ComplexNumber> internalList = FXCollections.observableArrayList();

    private ComplexNumberStack() {}

    /** This method provide the unique instance of ComplexNumberStack. */
    public static ComplexNumberStack getInstance() {
        if (instance == null)
            instance = new ComplexNumberStack();
        return instance;
    }

    // 保留标准栈的对外接口
    public ComplexNumber push(ComplexNumber item) {
        internalList.add(item);
        return item;
    }

    public ComplexNumber pop() {
        if (internalList.isEmpty()) {
            throw new EmptyStackException();
        }
        return internalList.remove(internalList.size() - 1);
    }

    public ComplexNumber peek() {
        if (internalList.isEmpty()) {
            throw new EmptyStackException();
        }
        return internalList.get(internalList.size() - 1);
    }

    public boolean isEmpty() {
        return internalList.isEmpty();
    }

    public int size() {
        return internalList.size();
    }

    /**
     * This method provides a secure implementation of massive pop of operandNumber operands from the stack
     *
     * @param operandNumber specifies the number of operands to be taken from the stack
     * @return an iterator of complexNumber taken
     */
    public Iterator<ComplexNumber> getOperand(int operandNumber) {
        List<ComplexNumber> operands = new ArrayList<>();
        for (int i = 0; i < operandNumber; i++) {
            try {
                operands.add(pop());
            } catch (EmptyStackException e) {
                Collections.reverse(operands);
                operands.forEach(this::push);
                throw new InvalidParameterException("There aren't enough operands into the stack");
            }
        }
        return operands.iterator();
    }

    // 对外暴露只读可观察列表,用于绑定控件
    public ObservableList<ComplexNumber> getObservableStack() {
        return FXCollections.unmodifiableObservableList(internalList);
    }
}

绑定控件示例

绑定到ListView

ListView<ComplexNumber> stackListView = new ListView<>();
// 直接绑定只读可观察集合即可,栈变更时列表自动更新
stackListView.setItems(ComplexNumberStack.getInstance().getObservableStack());

绑定到TableView

和绑定普通ObservableList逻辑完全一致,只需要给TableColumn设置对应的cellValueFactory读取ComplexNumber的属性即可。

注意:如果你的栈修改操作是在JavaFX应用线程之外执行的,需要用Platform.runLater()包裹修改逻辑,避免JavaFX界面更新抛出线程异常。

内容的提问来源于stack exchange,提问作者pairooo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 11:54:04