固定大小列表

Fixed-size List

提问人:jano 提问时间:11/15/2023 最后编辑:jano 更新时间:11/16/2023 访问量:60

问:

如何创建具有固定大小的 List 实例(无法对它们执行 add() 操作,但可以执行 set())?当我尝试更改为 IntelliJ 中没有出现编译器错误时。fields.set(i, board.get(i).get(x));fields.add(new SudokuField());


import java.util.*;

public class SudokuBoard {

    private final List<List<SudokuField>> board = new ArrayList<>();
    private final SudokuSolver solver;
    //private final List<ComponentObserver> observers = Arrays.asList(new ComponentObserver[3]);
    private final ComponentObserver[] observers = new ComponentObserver[3];
    private boolean state = true;

    public SudokuBoard(SudokuSolver solver) {
        this.solver = Objects.requireNonNull(solver);
        for (int i = 0; i < 9; i++) {
            List<SudokuField> row = Arrays.asList(new SudokuField[9]);
            for (int j = 0; j < 9; j++) {
                row.set(j, new SudokuField());
            }
            board.add(row);
        }
        for (int i = 0; i < 3; i++) {
            observers[i] = new ComponentObserver();
        }
    }

    public void solveGame() {
        solver.solve(this);
    }

    public boolean isSafe() {
        return checkBoard();
    }

    public int get(int y, int x) {
        return board.get(y).get(x).getFieldValue();
    }

    private  void setState() {
        state = observers[0].getCorrectState();
        state &= observers[1].getCorrectState();
        state &= observers[2].getCorrectState();
    }

    private void update(int y, int x) {
        observers[0].update(getRow(y));
        observers[1].update(getColumn(x));
        observers[2].update(getBox(y, x));
    }

    public void set(int y, int x, int value) {
        board.get(y).get(x).setFieldValue(value);
        update(y, x);
        setState();
    }

    public SudokuRow getRow(int y) {
        List<SudokuField> fields = Arrays.asList(new SudokuField[9]);
        for (int i = 0; i < 9; i++) {
            fields.set(i, board.get(y).get(i));
        }
        return new SudokuRow(fields);
    }

    public SudokuColumn getColumn(int x) {
        List<SudokuField> fields = Arrays.asList(new SudokuField[9]);
        for (int i = 0; i < 9; i++) {
            fields.set(i, board.get(i).get(x));
        }
        return new SudokuColumn(fields);
    }

    public SudokuBox getBox(int y, int x) {
        List<SudokuField> fields = Arrays.asList(new SudokuField[9]);
        int row = y / 3 * 3;
        int col = x / 3 * 3;
        int index = 0;
        for (int i = row; i < row + 3; i++) {
            for (int j = col; j < col + 3; j++) {
                fields.set(index, board.get(i).get(j));
                index++;
            }
        }
        return new SudokuBox(fields);
    }

    private boolean checkBoard() {
        return state;
    }
}
java 列表 arraylist

评论

0赞 Marvin 11/16/2023
这回答了你的问题吗?在 Java 中定义固定大小的列表
1赞 teapot418 11/16/2023
该接口有一个方法,无论您做什么,您都不会收到编译时错误。如果选择使方法未实现的实现,则可能会在运行时获得。ListaddUnsupportedOperationExceptionList
0赞 Maxime Pillier 11/16/2023
我认为您正在使用正确的代码来创建固定大小的列表。也许问题来自您尝试添加到列表中的内容?我想当你调用时它可以是空的:board.get[...]。得到[...]
0赞 Reilas 11/16/2023
这是一项很棒的练习,比大多数练习更具挑战性。

答:

3赞 Denis 11/16/2023 #1

我想你不需要.你可以只使用普通数组!java.util.List

public class Test {
    SudokuField[][] board = new int[size_1][size_2];
    
    public void get() {
        System.out.println(board[x][y]);
    }
    public void set() {
        board[x][y] = value;
    }
}

或者,如果你真的需要列表,你可以做这样的事情:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList<Object> board = new ArrayList<>(){
            @Override
            public boolean add(Object o) {
                if (super.size() + 1 >= YOUR_SIZE) {
                    return false; 
                }
                return super.add(o);
            }

            @Override
            public void add(int index, Object element) {
                if (super.size() + 1 >= YOUR_SIZE) {
                    return false;
                }
                super.add(index, element);
            }
        };
    }
}

它实际上在apchare commons库中。

Apache Commons 库提供了 FixedSizeList 类,该类不支持 add、remove 和 clear 方法(但允许使用 set 方法,因为它不会修改 List 的大小)。Eclipse 集合中的 FixedSizeList 也是如此。如果尝试调用这些方法之一,则列表的大小保持不变。

https://stackoverflow.com/a/5968535/22257686

0赞 Reilas 11/16/2023 #2

"...如何创建具有固定大小的列表实例......”

我不相信 Java 框架中有任何内容。

这是集合框架JavaDoc
集合框架(Java SE 21 和 JDK 21)。

@Denis 的答案类似,默认情况下只需使用固定长度的数组
数组(Java 教程>学习 Java™ 语言>语言基础知识)。

SudokuField[][] board = new SudokuField[9][9];

或者,封装 ArrayList 类,检查每个“add”方法的参数。

下面是一个示例。

class SudokuFieldList extends ArrayList<List<SudokuField>> {
    @Override
    public boolean add(List<SudokuField> e) {
        if (size() == 9 || e.size() > 9)
            throw new ListOutOfBoundsException();
        return super.add(e);
    }

    @Override
    public void add(int index, List<SudokuField> element) {
        if (size() == 9 || index >= 9 || element.size() > 9)
            throw new ListOutOfBoundsException();
        super.add(index, element);
    }

    @Override
    public boolean addAll(Collection<? extends List<SudokuField>> c) {
        if (size() == 9 || c.size() > 9)
            throw new ListOutOfBoundsException();
        return super.addAll(c);
    }

    @Override
    public boolean addAll(int index, Collection<? extends List<SudokuField>> c) {
        if (size() == 9 || index >= 9 || c.size() > 9)
            throw new ListOutOfBoundsException();
        return super.addAll(index, c);
    }

    static class ListOutOfBoundsException extends RuntimeException { }
}

而且,这里有一个示例用法;故意出错。

SudokuFieldList l = new SudokuFieldList();
for (int i = 0; i < 20; i++) l.add(List.of());
Exception in thread "main" Example$SudokuFieldList$ListOutOfBoundsException
    at Example$SudokuFieldList.add(Example.java:17)
    at Example.main(Example.java:10)

最后一点,这是一篇关于解决数独谜题的维基百科文章。
维基百科 – 数独求解算法