【问题标题】:Completable Future - Using Completable Future I am trying to the data from two different filesCompletable Future - 使用 Completable Future 我正在尝试来自两个不同文件的数据
【发布时间】:2020-02-22 22:35:21
【问题描述】:

我正在尝试从两个不同的文件中读取数据,一个是 csv 格式,另一个文件来自 xml 数据。使用 completeFuture 我正在尝试从两个文件中异步读取数据。我收到类型转换错误。 请让我知道我是否在下面的代码中遵循正确的方法来使用 completefuture 对象

例外:

java.lang.ClassCastException: class java.util.ArrayList cannot be cast to class java.util.function.Supplier (java.util.ArrayList and java.util.function.Supplier are in module java.base of loader 'bootstrap')

从主线程读取数据的代码

    CompletableFuture<Object> csvdata = CompletableFuture.supplyAsync((Supplier<Object>) processdatacsv());

    CompletableFuture<Object> xmldata1 = CompletableFuture.supplyAsync((Supplier<Object>) processxmldata());
    List<String[]> csvfiledata = null;
    if (csvdata.isDone())
        csvfiledata = (List<String[]>) csvdata.get();

    List<String[]> xmlfiledata = null;
    if (xmldata1.isDone())
        xmlfiledata = (List<String[]>) xmldata1.get();

    private List<String[]> processdatacsv() {
        CSVReader reader = null;
        Resource resource1 = new ClassPathResource("sample.csv");
        try {
            String csvFile = resource1.getFile().toString();
            reader = new CSVReader(new FileReader(csvFile));

            return reader.readAll();
        } catch (Exception e) {
            LOGGER.error("Error while process csv records");
            return null;
        }
    }

    private List<String[]> processxmldata() {
        Resource resource = new ClassPathResource("sample.xml");
        File file;
        try {
            file = resource.getFile();
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder;
            dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(file);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getElementsByTagName("record");
            System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
            List<String[]> dataList = new ArrayList<String[]>();
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);

                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element eElement = (Element) node;
                    String[] data = new String[3];
                    data[0] = eElement.getAttribute("reference").toString();
                    data[1] = eElement.getElementsByTagName("Number").item(0).getTextContent().toString();
                    data[2] = eElement.getElementsByTagName("des").item(0).getTextContent().toString();
                }
            }
            return dataList;
        } catch (Exception e) {

            LOGGER.error("Error while process csv records");
            return null;
        }
    }

【问题讨论】:

    标签: java completable-future


    【解决方案1】:

    对于CompletableFuture.supplyAsync,您需要Supplier。这不能通过将列表强制转换为Supplier&lt;Object&gt; 类型来完成。正确的做法是:

    CompletableFuture<List<String[]>> xmldata1 = CompletableFuture.supplyAsync(() -> processxmldata());
    

    使用Supplier 的原因是评估不能立即从构造Supplier 的语句开始。 Future 将在异步线程中开始计算。

    稍后,如果你真的需要结果,你必须等待它。最简单的方法就是:

    xmlfiledata = xmldata1.get(); 
    

    看一下get方法的javadoc。

    【讨论】:

      【解决方案2】:

      就像例外所说的那样:您不能只将列表强制转换为供应商对象。 Supplier 是一个对象,它有一个 get 方法来请求它提供的对象(在你的情况下是一个列表)。

      在您的代码中,文件不会被异步加载,因为您直接调用方法processdatacsvprocessxmldata,所以它们将被直接执行。要稍后(以及在另一个线程中)执行这些方法,您需要 Supplier(以便其他线程可以调用 get 方法并执行代码)。

      在您在问题中提供的代码中,像这样使用lambda expressions 是最简单的:

      CompletableFuture<List<String[]>> csvdata = CompletableFuture.supplyAsync(() -> processdatacsv());
      CompletableFuture<List<String[]>> xmldata1 = CompletableFuture.supplyAsync(() -> processxmldata());
      

      在这段代码 sn-p 中,() -&gt; processdatacsv() 部分可以解释为:创建一个新的 Supplier 对象,该对象从其方法 get 调用方法 processdatacsv

      或者你可以这样做(也许更容易理解):

      CompletableFuture<List<String[]>> csvdata = CompletableFuture.supplyAsync(new Supplier<List<String[]>>() {
          public List<String[]> get() {
              processdatacsv();
          }
      });
      CompletableFuture<List<String[]>> csvdata = CompletableFuture.supplyAsync(new Supplier<List<String[]>>() {
          public List<String[]> get() {
              processxmldata();
          }
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-02
        • 1970-01-01
        • 2022-12-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多