Как определить наличие объекта в ObservableList?
в этой программе я пытался реализовать добавление элементов в таблицу, но столкнулся с тем, что не могу реализовать ограничение на добавление копий, пытался использовать метод contains, но безуспешно.
package com.example.demo;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import java.util.Objects;
public class Controller {
private static ObservableList<Ticket> ticketsData = FXCollections.observableArrayList();
@FXML
private Button addButton;
@FXML
private Button delButton;
@FXML
private RadioButton bookingStatusRadioButton;
@FXML
private TableColumn<Ticket, String> bookingStatusTableColumn;
@FXML
private TableColumn<Ticket, String> flightCipherTableColumn;
@FXML
private TableColumn<Ticket, String> placeNumberTableColumn;
@FXML
private TextField flightCipherTextField;
@FXML
private Label infoLabel;
@FXML
private MenuItem saveAsMenuItem;
@FXML
private MenuItem saveMenuItem;
@FXML
private MenuItem lookMenuItem;
@FXML
private MenuItem openMenuItem;
@FXML
private MenuItem closeMenuItem;
@FXML
private MenuItem addMenuItem;
@FXML
private MenuItem aboutMenuItem;
@FXML
private TextField placeNumberTextField;
@FXML
private TableView<Ticket> tableTickets;
@FXML
void initialize() {
closeMenuItem.setOnAction(actionEvent -> System.exit(0));
aboutMenuItem.setOnAction(actionEvent -> showAlertWithDefaultHeaderText());
initData();
// устанавливаем тип и значение которое должно хранится в столбце
flightCipherTableColumn.setCellValueFactory(new PropertyValueFactory<Ticket, String>("flightCipher"));
placeNumberTableColumn.setCellValueFactory(new PropertyValueFactory<Ticket, String>("placeNumber"));
bookingStatusTableColumn.setCellValueFactory(new PropertyValueFactory<Ticket, String>("bookingStatus"));
// заполняем таблицу данными
tableTickets.setItems(ticketsData);
}
//ввод данных в таблицу из графического интерфейса
private void initData() {
addButton.setOnAction(actionEvent -> {
if (Objects.equals(flightCipherTextField.getText(), "")) {
infoLabel.setText("Необходимые поля пусты");
} else if (Objects.equals(placeNumberTextField.getText(), "")) {
infoLabel.setText("Необходимые поля пусты");
} else if (ticketsData.contains(new Ticket(flightCipherTextField.getText(), placeNumberTextField.getText(), bookingStatusRadioButton.isSelected()))) {
infoLabel.setText("Данный билет уже имеется в базе");
} else {
infoLabel.setText("Данные внесены");
ticketsData.add(new Ticket(flightCipherTextField.getText(), placeNumberTextField.getText(), bookingStatusRadioButton.isSelected()));
}
});
}
}
package com.example.demo;
public class Ticket {
private String flightCipher;
private String placeNumber;
private String bookingStatus;
public Ticket(String flightCipher, String placeNumber, boolean bookingStatus){
this.flightCipher = flightCipher;
this.placeNumber = placeNumber;
this.bookingStatus = String.valueOf(bookingStatus);
}
public String getFlightCipher() {
return flightCipher;
}
public void setFlightCipher(String flightCipher) {
this.flightCipher = flightCipher;
}
public String getPlaceNumber() {
return placeNumber;
}
public void setPlaceNumber(String placeNumber) {
this.placeNumber = placeNumber;
}
public String getBookingStatus() {
return bookingStatus;
}
public void setBookingStatus(String bookingStatus) {
this.bookingStatus = bookingStatus;
}
}
package com.example.demo;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(Main.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 640, 440);
stage.setTitle("База данных авиабилетов");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
Ответы (1 шт):
Метод .contains() проверяет наличие объекта в List через сравнение каждого объекта в коллекции с нужным объектом через метод .equals(). По умолчанию метод .equals() (унаследованный от класса Object) проверяет только равенство ссылок, но не равенство содержимого, поэтому .equals() возвращает true только если объект будет сравниваться с самим собой.
Чтобы сравнение шло по содержимому полей объекта, нужно переопределить метод .equals(), в нем делать сравнение двух объектов по их полям.
Если пишите в Intellij IDEA, можно сгенерировать этот метод автоматически: внутри класса нажимаете Alt+Enter, в появившемся меню "Generate" выбираете "equals() and hashCode()", дальше уточняете параметры (стиль, сравниваемые поля, и т.д.)
hashCode для вашей задачи (проверки наличия внутри ObservableList или List в целом) не нужен, но понадобится, если вы захотите хранить и проверять наличие вашего объекта внутри Set или использовать как ключ в Map.
Я приведу немного модифицированный вариант .equals() с комментариями:
@Override
public boolean equals(Object other) {
if (this == other) return true; // Если один и тот же объект, значит объекты равны
if (other == null || getClass() != other.getClass()) return false; // Если классы не совпадают, значит объекты разные
Ticket ticket = (Ticket) other;
// Если значения полей совпадают, значит объекты равны
return flightCipher.equals(ticket.flightCipher)
&& placeNumber.equals(ticket.placeNumber)
&& bookingStatus.equals(ticket.bookingStatus);
}
Для проверки можно использовать такой код:
ObservableList<Ticket> ticketsData = FXCollections.observableArrayList();
ticketsData.addAll(
new Ticket("123", "place 111", true),
new Ticket("456", "place 123", true),
new Ticket("789", "place 652", false)
);
// Выведет "contains"
if (ticketsData.contains(new Ticket("456", "place 123", true))) {
System.out.println("contains");
} else {
System.out.println("doesn't contain");
}
// Выведет "doesn't contain"
if (ticketsData.contains(new Ticket("erewr", "place 1234", false))) {
System.out.println("contains");
} else {
System.out.println("doesn't contain");
}