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

Java Swing栈式矩形管理应用代码优化及按面积排序并在DefaultListModel展示的实现咨询

问题解答

一、关于维护栈和DefaultListModel的实践优化

当前你分别向栈和DefaultListModel重复添加格式化字符串的方式不是良好实践,主要存在两个问题:

  • 数据冗余:同一个矩形的信息被存储了两次(栈里的字符串和ListModel里的字符串),后续如果需要修改矩形属性,极易出现数据不一致的情况。
  • 可维护性差:格式化字符串的代码重复出现,后续要调整展示格式时,得在多个地方修改,容易出错。

更好的实现方式:封装矩形数据模型

建议创建一个专门的Rectangle类来封装矩形的所有属性,这样既能统一存储数据,又能彻底避免重复代码:

public class Rectangle {
    private int x;
    private int y;
    private int width;
    private int height;

    public Rectangle(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    // 计算面积的方法
    public int getArea() {
        return width * height;
    }

    // 重写toString,统一格式化展示内容
    @Override
    public String toString() {
        return String.format("Upper left point: (%d,%d) width: %d height: %d Surface area: %d",
                x, y, width, height, getArea());
    }

    // Getter方法(排序时需要用到属性)
    public int getX() { return x; }
    public int getY() { return y; }
    public int getWidth() { return width; }
    public int getHeight() { return height; }
}

基于模型同步栈和ListModel

现在栈里存储Rectangle对象,DefaultListModel完全基于栈的内容同步更新,这样只需要维护栈这一个数据源,彻底避免数据不一致:

// 修改栈的定义为存储Rectangle对象
private Deque<Rectangle> stack = new ArrayDeque<>();
private DefaultListModel<String> dlm = new DefaultListModel<>();

// 添加矩形时的逻辑
btnAdd.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        DlgRectangle dlgRectangle = new DlgRectangle();
        dlgRectangle.setVisible(true);
        if (dlgRectangle.isOk) {
            try {
                int x = Integer.parseInt(dlgRectangle.txtX.getText());
                int y = Integer.parseInt(dlgRectangle.txtY.getText());
                int width = Integer.parseInt(dlgRectangle.txtWidth.getText());
                int height = Integer.parseInt(dlgRectangle.txtHeight.getText());
                
                Rectangle rect = new Rectangle(x, y, width, height);
                stack.addFirst(rect);
                // 同步更新ListModel,直接复用rect的toString方法
                dlm.add(0, rect.toString());
                System.out.println(stack);
            } catch (NumberFormatException ex) {
                // 处理输入非数字的情况,比如弹出提示框
                JOptionPane.showMessageDialog(null, "Please enter valid numbers!");
            }
        }
    }
});

// 删除矩形时的逻辑
btnDelete.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        if (!stack.isEmpty()) {
            stack.pop();
            dlm.remove(0);
            System.out.println(stack);
        } else {
            System.out.println("Stack is empty");
            JOptionPane.showMessageDialog(null, "Stack is empty!");
        }
    }
});

这样改造后,你只需要维护栈这一个数据源,ListModel完全基于栈的内容更新,不仅减少了重复代码,还从根源上避免了数据不一致的问题。

二、按矩形面积对栈进行排序

首先要明确:栈(LIFO)本身是一种无序结构,核心特性是后进先出,不支持直接排序。如果你需要对栈中的矩形按面积排序,可以通过以下步骤实现:

  1. 将栈中的所有元素转移到一个可排序的集合(比如ArrayList)中;
  2. 对集合按面积进行排序(升序或降序);
  3. 将排序后的集合重新放回栈中;
  4. 同步更新DefaultListModel。

具体实现代码

比如添加一个“Sort by Area”按钮,点击后执行排序逻辑:

JButton btnSort = new JButton("Sort by Area");
btnSort.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        if (stack.isEmpty()) {
            JOptionPane.showMessageDialog(null, "Stack is empty, nothing to sort!");
            return;
        }

        // 1. 将栈元素转移到ArrayList
        List<Rectangle> rectList = new ArrayList<>(stack);
        
        // 2. 按面积排序(这里是升序,要降序的话用Comparator.reverseOrder())
        rectList.sort(Comparator.comparingInt(Rectangle::getArea));
        
        // 3. 清空原栈,将排序后的元素重新压入栈
        // 注意:栈是LIFO,若希望JList中展示最大面积在前,需反向遍历列表压入
        stack.clear();
        for (int i = rectList.size() - 1; i >= 0; i--) {
            stack.addFirst(rectList.get(i));
        }
        // 若希望最小面积在前,直接正向遍历压入即可
        // rectList.forEach(stack::addFirst);
        
        // 4. 同步更新ListModel
        dlm.clear();
        stack.forEach(rect -> dlm.addElement(rect.toString()));
    }
});

关键说明

  • 排序后重新压入栈时,要注意栈的LIFO特性:如果希望JList中展示的顺序是从面积最大到最小,需要把排序后的列表反向遍历,将最大的元素先压入栈(这样栈顶就是最大的,JList的第一个元素也是最大的);如果希望升序展示,直接正向遍历压入即可。
  • 排序时使用Comparator.comparingInt(Rectangle::getArea)非常简洁,你也可以自定义比较逻辑(比如面积相同时按宽度排序)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 12:57:26