Java 如何创建转换列表的通用方法<;对象>;进入可观察列表<;S>;和地图<;T、 S>;?

Java 如何创建转换列表的通用方法<;对象>;进入可观察列表<;S>;和地图<;T、 S>;?,java,generics,javafx-8,Java,Generics,Javafx 8,一个相对的Java新手问题 我有一些代码,可以从二维列表创建一个可观察列表可观察列表和一个哈希映射映射 我想将代码转换成一个通用方法,该方法可以处理任何表模型 但是,我一直在了解如何在代码中的两个地方用泛型类型参数替换特定类型。有人能帮我吗 我当前的非通用代码如下所示: //A database table is loaded into resultSet private static List<List<Object>> resultSet = new ArrayLis

一个相对的Java新手问题

我有一些代码,可以从二维列表创建一个可观察列表
可观察列表
和一个哈希映射
映射

我想将代码转换成一个通用方法,该方法可以处理任何表模型

但是,我一直在了解如何在代码中的两个地方用泛型类型参数替换特定类型。有人能帮我吗

我当前的非通用代码如下所示:

//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);

});

让我们分析一下您需要的功能:

  • 根据
    列表创建一个对象(这可以分为两部分:创建对象和初始化对象)
  • 从对象获取id属性
  • 至少对于对象创建,您应该使用提供实现的对象。如果要将其与初始化结合使用,可以使用
    函数
    进行此操作,如果要将其分开,请使用
    供应商

    对于初始化和/或获取id,您可以使用
    S
    本身的方法,这要求您通过一个公共基类或包含执行此操作的方法的接口来限制其类型。或者,您也可以使用包含实现的对象,即
    BiConsumer
    Function

    示例1:实现id/初始化的公共接口 示例2:使用包含实现的不同对象

    注意:
    映射中存储基于可变属性的对象时要小心。对存储在地图中的对象调用
    setPK
    可以很容易地破坏您的代码…

    太好了,fabian,再次感谢您。我尝试了示例2,因为它更容易理解。哈希映射加载正常,但可观察列表为空。所以我加了
    ol.add(o)
    初始值设定项之后。接受(o,resultRow),这就行了。还感谢您提醒我们,映射中的可变属性可能会破坏代码。我可以看到这是如何发生的,当我进一步编写应用程序时,我会记住这一点。我想我现在明白了(经过大量的阅读和实验!),并在我的应用程序中运行了它。我将TableModel声明更改为
    公共类TableModel implements DatabaseObject
    ,并向TableModel添加了
    getId()
    方法,如下所示:
    @Override public Integer getId(){return this.PK.get();}
    。对吗?谢谢
    //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
    
        });
    
    }
    
    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);
        }
    
    }
    
    public interface DatabaseObject<T> {
        void addList(List<Object> list);
    
        T getId();
    }
    
    private static <K, E extends DatabaseObject<? extends K>> void loadTable(ObservableList<E> ol, Map<K, E> hm, List<List<Object>> rs, Supplier<E> factory) {
        for (List<Object> resultRow : rs) {
            E o = factory.get();
            o.addList(resultRow);
            hm.put(o.getId(), o);
            ol.add(o);
        }
    }
    
    loadTable(olModel, mapModel, resultSet, TableModel::new);
    
    private static <S, T> void loadTable(
            ObservableList<S> ol,
            Map<T, S> hm,
            List<List<Object>> rs,
            Supplier<? extends S> factory,
            BiConsumer<? super S, List<Object>> initializer,
            Function<? super S, ? extends T> idExtractor) {
    
        for (List<Object> resultRow : rs) {
            S o = factory.get();
            initializer.accept(o, resultRow);
            hm.put(idExtractor.apply(o), o);
            ol.add(o);
        }
    }
    
    loadTable(olModel, mapModel, resultSet, TableModel::new, TableModel::addList, TableModel::getPK);