用Java访问数据集的最快方式是什么?

用Java访问数据集的最快方式是什么?

问题描述:

我有一个大文件,有180万行数据,我需要为我正在编写的机器学习程序读取数据。数据目前在CSV文件中,但显然我可以根据需要将其放入数据库或其他结构中 - 不需要定期更新。用Java访问数据集的最快方式是什么?

我目前使用的代码如下。我首先将数据导入数组列表,然后将它传递给表模型。这是非常缓慢的,目前需要6分钟才能执行前10,000行,这是不可接受的,因为我需要能够经常对数据测试不同的算法。

我的程序只需要访问每行数据一次,所以不需要将整个数据集保存在RAM中。我最好从数据库中读取数据,还是有更好的方法来逐行读取CSV文件,但要快得多吗?

import java.io.File; 
import java.io.FileNotFoundException; 
import java.util.ArrayList; 
import java.util.Scanner; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableModel; 

public class CSVpaser { 

public static TableModel parse(File f) throws FileNotFoundException { 
    ArrayList<String> headers = new ArrayList<String>(); 
    ArrayList<String> oneDdata = new ArrayList<String>(); 
    //Get the headers of the table. 
    Scanner lineScan = new Scanner(f); 
    Scanner s = new Scanner(lineScan.nextLine()); 
    s.useDelimiter(","); 
    while (s.hasNext()) { 
     headers.add(s.next()); 
    } 

    //Now go through each line of the table and add each cell to the array list 
    while (lineScan.hasNextLine()) { 
     s = new Scanner(lineScan.nextLine()); 
     s.useDelimiter(", *"); 
     while (s.hasNext()) { 
      oneDdata.add(s.next()); 
     } 
    } 
    String[][] data = new String[oneDdata.size()/headers.size()][headers.size()]; 
    int numberRows = oneDdata.size()/headers.size(); 

    // Move the data into a vanilla array so it can be put in a table. 
    for (int x = 0; x < numberRows; x++) { 
     for (int y = 0; y < headers.size(); y++) { 
      data[x][y] = oneDdata.remove(0); 
     } 
    } 

    // Create a table and return it 
    return new DefaultTableModel(data, headers.toArray()); 


} 

更新: 基于我在我已经重写了代码,它现在在3秒内运行,而不是6分钟(10000行),这意味着只有十几分钟整个文件的答案收到的反馈。 ..但对于如何加快它的任何进一步的建议,将不胜感激:

 //load data file 
    File f = new File("data/primary_training_short.csv"); 
Scanner lineScan = new Scanner(f); 
    Scanner s = new Scanner(lineScan.nextLine()); 
    s.useDelimiter(","); 

    //now go through each line of the results 
    while (lineScan.hasNextLine()) { 
     s = new Scanner(lineScan.nextLine()); 
     s.useDelimiter(", *"); 
     String[] data = new String[NUM_COLUMNS]; 

     //get the data out of the CSV file so I can access it 
     int x = 0; 
     while (s.hasNext()) { 
      data[x] = (s.next()); 
      x++; 
     } 
     //insert code here which is excecuted each line 
    } 
+0

尝试像网站分页! – alibenmessaoud 2011-04-16 03:11:22

data[x][y] = oneDdata.remove(0); 

这将是非常低效的。每次从ArrayList中删除第一个条目时,所有其他条目都需要向下移动。

您至少需要创建自定义TableModel,因此您不必复制两次数据。

如果您想保留数据库中的数据,然后在网络中搜索ResultSet TableModel。

如果你想保持它的CSV格式,那么你可以使用ArrayList作为TableModel的数据存储。所以你的扫描器代码会直接将数据读入ArrayList。对于这样的解决方案,请参阅List Table Model。或者您可能想要使用Bean Table Model

当然真正的问题是谁将有时间浏览所有的1.8M记录?所以你真的应该使用数据库并且有查询逻辑来过滤从数据库返回的行。

我的程序只需要访问一次数据的每一行,所以没有必要保持整个数据集在RAM

,那你为什么JTable中显示它?这意味着整个数据将存储在内存中。

+0

谢谢,我会尝试重做它,以避免删除功能,并让你知道我如何相处 – TechnoTony 2011-04-16 03:15:43

+0

我摆脱了JTable和.remove功能,现在它运行在3秒而不是6分钟。这意味着使用CSV文件整个表格需要10分钟 - 如果我从sqllite数据库读取数据,速度会更快吗?我仍然需要访问数据库中的每一行来运行算法 – TechnoTony 2011-04-16 03:56:45

+0

据我所知,如果您只是使用它来简单地按顺序检索所有记录,数据库访问将会变慢,但我相信论坛中的其他人会有更好的理念。您应该更新您的代码,以便我们检查其他改进。例如,尝试使用更合理的条目数来创建ArrayList,以便在它满了时不必分配更多空间。 – camickr 2011-04-16 04:09:25

Sqllite是一种重量很轻的基于文件的数据库和雅对我来说,解决您的问题的最佳解决方案。

看看这个非常好的驱动程序为java。我将它用于我的NLP项目之一,它的工作非常好。

+0

谢谢,有帮助的回复。我现在要尝试使用CSV,所以我不必学习新的课程,但如果这不起作用,我一定会试试这个... – TechnoTony 2011-04-16 03:19:29

这就是我所理解的:你的要求是在加载的数据上执行一些算法,

  • 负载的一组数据
  • 进行一些计算
  • 加载另一组数据
  • 执行更多的计算,依此类推,直到我们达到在CSV结束

由于两组数据之间没有相关性,并且您对数据执行的算法/计算是自定义逻辑(SQL中没有内置函数),这意味着即使不使用任何语言,也可以在Java中执行此操作数据库和这个应该是最快的。

但是,如果您对两组数据执行的逻辑/计算在SQL中得到了一些等效函数,并且有一个单独的数据库运行时具有良好的硬件(即更多的内存/ CPU),则执行这整个逻辑通过SQL中的过程/函数可以执行得更好。

您可以使用opencsv软件包,它们的CSVReader可以迭代大型CSV文件,您还应该使用在线学习方法,例如NaiveBayes,LinearRegression等大型数据。