package datastruct; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Matrix<T> { private final List<List<T>> matrix; private final int width; private final int height; public Matrix(int width, int height, MatrixInitializer<T> initializer) { this.width = width; this.height = height; this.matrix = new ArrayList<>(); this.initializeWith(initializer); } public Matrix(int width, int height, T initialValue) { this(width, height, new ConstantMatrixInitializer<>(initialValue)); } private void initializeWith(MatrixInitializer<T> initializer) { for (int x = 0; x < width; x++) { List<T> row = new ArrayList<>(); this.matrix.add(row); for (int y = 0; y < height; y++) { row.add(initializer.initialValueAt(Coordinate.of(x,y))); } } } public T get(int x, int y) { return this.matrix.get(x).get(y); } public T get(Coordinate coord) { return this.get(coord.x(), coord.y()); } public void set(int x, int y, T value) { this.matrix.get(x).set(y,value); } public void set(Coordinate coord, T value) { this.set(coord.x(), coord.y(), value); } public Iterator<T> iterator() { Iterator<Coordinate> coordIterator = this.coordinatesIterator(); return new MatrixIterator(this, coordIterator); } public Iterable<Coordinate> coordinates() { return this::coordinatesIterator; } private Iterator<Coordinate> coordinatesIterator() { return new CoordinateIterator(this.width, this.height); } public Lens<T> at(int x, int y) { return new Lens<T>() { @Override public T get() { return Matrix.this.get(x,y); } @Override public void set(T value) { Matrix.this.set(x,y,value); } }; } public Lens<T> at(Coordinate coord) { return this.at(coord.x(), coord.y()); } }