Изменение одной строки в 2D ArrayList в java изменяет все строки

Я хочу забронировать одно место в кинозале в соответствии с вводом, но когда я пытаюсь это сделать, он меняет все ряды.

Забронированное место обозначается буквой «B».

Метод, меняющий состояние кинозала:

public void bookSeat(int row, int seat) {
        this.seatsArrangement.get(row  - 1).set(seat - 1, 'B');
    }

Вход и выход:

Enter the number of rows:
> 7
Enter the number of seats in each row:
> 8
Cinema:
  1 2 3 4 5 6 7 8 
1 S S S S S S S S 
2 S S S S S S S S 
3 S S S S S S S S 
4 S S S S S S S S 
5 S S S S S S S S 
6 S S S S S S S S 
7 S S S S S S S S 
Enter a row number:
> 2
Enter a seat number in that row:
> 4
Cinema:
  1 2 3 4 5 6 7 8 
1 S S S B S S S S 
2 S S S B S S S S 
3 S S S B S S S S 
4 S S S B S S S S 
5 S S S B S S S S 
6 S S S B S S S S 
7 S S S B S S S S

весь код:

package cinema;
import java.util.*;
public class Cinema {

    private final int rows;
    private final int seats;
    private final List<List<Character>> seatsArrangement = new ArrayList<>();

    public Cinema (int rows, int seats) {
        this.rows = rows;
        this.seats = seats;
        List<Character> rowArrangement = new ArrayList<>();
        while (seats-- != 0) {
            rowArrangement.add('S');
        }
        while (rows-- != 0) {
            seatsArrangement.add(rowArrangement);
        }
    }

    public int calculateProfit() {
        if (this.rows * this.seats <= 60) {
            return this.rows * this.seats * 10;
        } else {
            return (int) ((Math.floor(this.rows / 2.0) * 10 + (this.rows - Math.floor(this.rows / 2.0)) * 8) * this.seats);
        }
    }

    public void showSeatsArrangement() {
        System.out.print("Cinema:\n  ");
        int i = 1;
        while (i <= this.seats) {
            System.out.printf("%d ", i++);
        }
        i = 1;
        for (var row : this.seatsArrangement) {
            System.out.print("\n" + i + " ");
            for (var seat : row) {
                System.out.printf("%c ", seat);
            }
            ++i;
        }
    }

    public void bookSeat(int row, int seat) {
        this.seatsArrangement.get(row  - 1).set(seat - 1, 'B');
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.println("Enter the number of rows:");
        int rows = sc.nextInt();
        System.out.println("Enter the number of seats in each row:");
        int seats = sc.nextInt();

        Cinema cinema = new Cinema(rows, seats);
        cinema.showSeatsArrangement();

        System.out.println("\nEnter a row number:");
        int row = sc.nextInt();
        System.out.println("Enter a seat number in that row:");
        int seat = sc.nextInt();

        cinema.bookSeat(row, seat);
        cinema.showSeatsArrangement();
    }
}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
388
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Каждый элемент вашего массива seatArrangement является одним и тем же ArrayList. Вы добавляете тот же самый ArrayList, rowArrangement, в seatArrangement. Чтобы исправить это, создайте копии rowArrangement во втором цикле while. например

        while (rows-- != 0) {
            List<Integer> tmp = new ArrayList<>(rowArrangement);
            seatsArrangement.add(tmp);
        }

Спасибо @MCI за вашу помощь, это была глупая ошибка.

сделал несколько изменений в конструкторе:

оригинальная версия:

 public Cinema (int rows, int seats) {
        this.rows = rows;
        this.seats = seats;
        List<Character> rowArrangement = new ArrayList<>();
        while (seats-- != 0) {
            rowArrangement.add('S');
        }
        while (rows-- != 0) {
            seatsArrangement.add(rowArrangement);
        }
    }

Рабочая версия:

public Cinema(int rows, int seats) {
        this.rows = rows;
        this.seats = seats;
        List<Character> rowArrangement = new ArrayList<>();
        while (seats-- != 0) {
            rowArrangement.add('S');
        }
        while (rows-- != 0) {
            seatsArrangement.add(new ArrayList<>(rowArrangement));
        }
    }

Но почему-то rowArrangment.clone() не работает, получаю эту ошибку

'clone()' имеет защищенный доступ в 'java.lang.Object'

Это решило проблему, но я понятия не имею, почему?

((ArrayList) rowArrangement).clone();

Обновлено: причина, по которой нам нужно явно приводить rowArrangment, заключается в том, что метод clone() является неотъемлемым свойством ArrayList, и поскольку я использовал List для ссылки на rowArrangement, поэтому я не могу вызвать метод clone() непосредственно на нем, потому что повышение приведения не поддерживает доступ к методам подкласса.

Другие вопросы по теме