Относительный вопрос новичка в Java.
У меня есть код, который создает наблюдаемый список ObservableList<TableModel>
и хэш-карту Map<Integer, TableModel>
из двумерного списка List<List<Object>>
.
Я хотел бы преобразовать код в универсальный метод, который будет работать с любой табличной моделью.
Однако я застрял в знании того, как заменить конкретные типы параметрами универсального типа в двух местах в моем коде.Может ли кто-нибудь помочь мне, пожалуйста?
Мой текущий неуниверсальный код выглядит следующим образом:
//A database table is loaded into resultSet
private static List<List<Object>> resultSet = new ArrayList<>();
//...
ObservableList<TableModel> olModel = FXCollections.observableArrayList();
Map<Integer, TableModel> mapModel = new HashMap<>();
resultSet.forEach(resultRow -> {
//Load the observable list
TableModel row = new TableModel();
row.addList(resultRow);
olModel.add(row);
//Load the hash map
mapModel.put(row.getPK(), row);
});
Я пытаюсь «обобщить» его следующим образом и указал места, где яЯ застрял:
//Call a generic method
loadTableOLAndHM(olModel, mapModel, resultSet);
//...
private <S, T> void loadTableOLAndHM(ObservableList<S> ol, Map<T, S> hm, List<List<Object>> rs) {
rs.forEach(resultRow -> {
S row = new [WHAT-GOES-HERE?] (); //(1) STUCK HERE
row.addList(resultRow);
ol.add( (S) row);
hm.put( (T) row.getPK(), (S) row); //(2) STUCK HERE - GETS "incompatible types" ERROR
});
}
Я могу обойти ошибку "несовместимых типов" в (2), изменив getPK()
, чтобы он возвращал Integer
вместо int
, но не знаю, так ли этоправильный способ исправить это.Первичным ключом БД будут и другие типы данных для других таблиц, поэтому я не уверен, что делать.
Я не знаю, как исправить (1).
IЯ читал и экспериментировал с различными способами составления списка результатов, но, похоже, ни один из них не работает.Еще я попробовал передать TableModel.class
в качестве параметра универсальному методу, но не смог понять, как его использовать.
Вот MVCE, который показывает, что я сейчас делаю, и какну, что я хотел бы сделать.Если у вас есть время помочь, я был бы очень признателен.Спасибо!
Я использую JavaFX8, NetBeans 8.2 и Scene Builder 8.3.
package test11;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Test11 extends Application {
private static List<List<Object>> resultSet = new ArrayList<>();
private Parent createContent() {
BorderPane content = new BorderPane();
//Load dummy data into resultSet for testing
loadDummyData();
//***********************************************************************
//WHAT I'M CURRENTLY DOING
//Observable list and hash map for the loaded table
ObservableList<TableModel> olModel = FXCollections.observableArrayList();
Map<Integer, TableModel> mapModel = new HashMap<>();
resultSet.forEach(resultRow -> {
//Load the observable list
TableModel row = new TableModel();
row.addList(resultRow);
olModel.add(row);
//Load the hash map
mapModel.put(row.getPK(), row);
});
systemOutIt("***** CURRENT WAY ******", olModel, mapModel);
olModel.clear();
mapModel.clear();
//***********************************************************************
//WHAT I WOULD LIKE TO BE ABLE TO DO
loadTableOLAndHM(olModel, mapModel, resultSet);
systemOutIt("***** NEW WAY ******", olModel, mapModel);
return content;
}
private <S, T> void loadTableOLAndHM(ObservableList<S> ol, Map<T, S> hm, List<List<Object>> rs) {
rs.forEach(resultRow -> {
//==>STUCK GENERICISING THE FOLLOWING LINE:
//original line TableModel row = new TableModel();
// S row = new [WHAT-GOES-HERE?] ();
// row.addList(resultRow);
// ol.add( (S) row);
//==>STUCK GENERICISING THE FOLLOWING LINE
//Error "incompatible types: int cannot be converted to T"
//In the Map declaration, T is Integer.
//In TableModel, getPK() returns int.
// hm.put( (T) row.getPK(), (S) row);
});
}
public static class TableModel {
private final SimpleIntegerProperty PK;
private final SimpleStringProperty dataField;
private TableModel() {
this(0, "");
}
private TableModel(int PK, String dataField) {
this.PK = new SimpleIntegerProperty(PK);
this.dataField = new SimpleStringProperty(dataField);
}
public int getPK() {
return PK.get();
}
public void setPK(int PK) {
this.PK.set(PK);
}
public IntegerProperty PKProperty() {
return PK;
}
public String getDataField() {
return dataField.get();
}
public void setDataField(String dataField) {
this.dataField.set(dataField);
}
public StringProperty dataFieldProperty() {
return dataField;
}
public void addList(List<Object> list) {
this.PK.set( (int) list.get(0));
this.dataField.set( (String) list.get(1));
}
}
private void loadDummyData(){
for ( int i=1; i<4; i++ ) {
List<Object> resultSetRow = new ArrayList<>();
resultSetRow.add(i);
resultSetRow.add("string"+i);
resultSet.add(resultSetRow);
}
}
private void systemOutIt(String whichWay, ObservableList<TableModel> ol, Map<Integer, TableModel> hm) {
System.out.println(whichWay);
System.out.println("ObservableList, size is " + ol.size());
for ( int i=0; i<ol.size(); i++ ) {
System.out.println(" ol fields = " + ol.get(i).getPK() + ", " + ol.get(i).getDataField());
System.out.println(" map dataField value = " + hm.get(ol.get(i).getPK()).getDataField());
}
}
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
stage.setTitle("Test");
stage.setHeight(250);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}