【问题标题】:Efficient Algorithm for reading data from Excel Spreadsheet in Java从 Java 中的 Excel 电子表格中读取数据的高效算法
【发布时间】:2013-07-04 00:03:57
【问题描述】:

我正在做一个小项目,将电子表格中的一方(也称为客户端)数据读取到两个哈希图中。一个跟踪每一方,其值为对象 Party,另一个嵌入在跟踪每一方数据的 Party Object 中。事情是,我这样做的方式是使用两个 for 循环,众所周知,这是一个 O(N^2) 算法。现在的方式是大约 500 行(或 500 个方)和大约 65 列(或 65 个标签/值),因此在元素数量上它并不是什么大问题。但是,我被告知它可能必须处理超过 2500 万行,在这种情况下 O(N^2) 是一个问题(我猜的列在技术上不是 O(N^2),但列数可以扩展它不一定设置为 65)。

长话短说,我需要有关如何减少运行时间的提示,但我真的想不出任何其他方法来访问工作表中的每个单元格。

以下是相关代码:

package storage;

import java.io.File;
import java.util.HashMap;


import jxl.Sheet;
import jxl.Workbook;

import pojo.Party;

public class PartyStructure {

    private static HashMap<String, Party> map;
    private static PartyStructure partyStructure;
    private String inputFile = "C:/Users/joayers/Documents/API Project Information/Sample Data.xls";
    File excelData = new File(inputFile);

    private PartyStructure() throws Exception
    {
        map = new HashMap<String, Party>();
        readData();
    }

    public static HashMap<String,Party> getPartyCollection() throws Exception
    {
        if(partyStructure==null)
        {
            partyStructure = new PartyStructure();
        }
        return map;
    }
    private void readData() throws Exception 
    {
        Workbook w=Workbook.getWorkbook(excelData);
        Sheet sheet = w.getSheet(0);
        String party_name;
        String labelName;
        String dataField;

        for(int i=1;i<sheet.getRows();i++)
        {
            party_name = sheet.getCell(2, i).getContents().toString();
            //map is a Hashmap<String, Party> 
            map.put(party_name, new Party());

                for(int j=0;j<sheet.getColumns();j++)
                {
                    labelName = sheet.getCell(j, 0).getContents().toString();
                    dataField = sheet.getCell(j, i).getContents().toString();
                    Party party = map.get(party_name);
                    //getPartyInfo is a getter for a HashMap<String, String> that holds values associated with the keys (the labels in excel)
                    party.getPartyInfo().put(labelName, dataField);
                }
        }   
    }

}

另外,hashmap 和 hashtable 之间有什么区别吗?它们看起来是一样的

【问题讨论】:

  • 我不确定说算法是 O(N^2) 是否正确。这里 N 是单元格的数量,所以这是 O(N)。
  • Excel 中的行数限制在百万范围内 (answers.microsoft.com/en-us/office/forum/office_2010-excel/…),而且我认为 Raedwald 对此是正确的,所以这里没有问题。
  • 现在想想就尴尬,你说的完全正确

标签: java algorithm excel api


【解决方案1】:

我建议的第一件事是将声明放在循环之外(之前):

String party_name = sheet.getCell(2, i).getContents().toString();    // etc.

还有labelName、dataField、party。在循环之前声明:

String party_name = "";    // etc.

您还没有说明您使用的 Excel 库是什么。一些库有,例如 getUsedRange 来缩小您正在搜索的单元格,以及(可能)从 Range 中填充数组的方法。

【讨论】:

  • 在循环之前声明字段有什么好处?它可以节省内存吗?此外,更新为包括整个班级,我正在使用 jxl 库。
  • 我不知道编译器是否会优化您当前的代码,或者它可能会产生什么性能改进。但是,简单地说,没有必要在循环中不断地重新声明变量。
  • 好的,谢谢 我喜欢尽可能保持良好的风格,除了表格中的所有内容外,没有指定范围。有没有办法将运行时间减少 N 倍或一个大常数?
  • 我只是快速浏览了一下,但 jxl 库看起来有点旧,而且可能有限。其他人可能会推荐一个更好的库。如果您可以获取已用范围并将其放入数组中,那么我希望性能会有所提高。
  • 如果 Excel 文件只包含一个表,那么应该可以将其视为数据库并使用数据库连接将数据读入 RecordSet。不过,我还没有用 Java 做到这一点。
【解决方案2】:

如果您必须读取所有单元格,并在哈希图中收集内容,您可以考虑并行化此任务:您可以按行划分任务:让一些线程在工作表中的不同区域工作。

在您的情况下,您可能会在单独的映射中收集线程结果,最后您可以将它们放在一起(因此无需在哈希映射上同步)。

HashMap 未同步,Hashtable 已同步 (details here)。

【讨论】:

  • 哎呀,我想到目前为止我在学校有一个作业,我必须创建多个线程,它更像是“只需插入此代码,不要担心它的作用”而不是关于如何创建多线程程序的作业。绝对是我需要研究的东西。
猜你喜欢
  • 1970-01-01
  • 2020-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-03
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多