Java - 有一个巨大的 ArrayList(超过 100 万),如何在可接受的时间内创建它的 String?

标签 java mysql csv arraylist

正如我提到的,我有这种格式的大量 ArrayList:

List<List<String>> alist;

我通过外部数据库系统从一些 .CSV 中获取列表。 (我写了一个 Visual Objects 脚本来导出我们需要进行一些计算的数据)

获得 .CSV 后,我将内容加载到我的列表中,如下所示:

String line;
       alist = new ArrayList<List<String>>();
       int i=0;
    // Datei laden, und anschließend die Zeilen der CSV in eine ArrayList speichern 

       try {             

            br = new BufferedReader(new FileReader(path));
            while((line = br.readLine()) != null)
            {
                line = line.replace(",", ".");
                if(line.endsWith(delimitter))
                    line = line + " ";
                alist.add(Arrays.asList(line.split(delimitter)));
                i++;
                if(i==10000000)
                    break;
            }       

        }

将数据存储在我的 ArrayList 中大约需要 15900 毫秒(约 110 万行和 11 列)。我想还不错。 现在,我有了我需要的格式的列表,我想从中创建一个插入,这样我们就可以将数据导入到我们的数据库中。 我正在创建这样的插入:

public String getInsertString()
    {
        // Tabelle ergibt sich aus dem Dateinamen, ohne das .csv
        String insert="REPLACE INTO "+tablename + " (";

        // Spaltennamen aus Array auslesen, immer die erste Zeile des CSV
        for(int i=0; i< alist.get(0).size();i++)
        {
            if(i==0)
                insert = insert + alist.get(0).get(i).trim();
            else
                insert = insert + " ,"+ alist.get(0).get(i).trim();
        }
        insert= insert + ") \rVALUES";

        // Values der SPalten in den Insert schreiben + korreckte Syntax des Bfehels sicherstellen usw.
        for(int i=1;i < alist.size();i++) // Size nach "unten" in der 2D Liste
        {

            insert= insert +"(";
            for(int j=0; j < alist.get(0).size();j++) // Size nach "rechts" in der 2D Liste
            {
                // bei dem ersten ohne "," starten, damit die Syntax stimmt
                // Sollte der aktuelle Wert eine Zahl oder "null" sein, keine "'" setzen. Ansonsten "'" setzen fuer den Insert in die DB
                if(j==0)
                {           
                    if((StringUtils.isStrictlyNumeric(alist.get(i).get(j).trim())) || alist.get(i).get(j).trim().contains("null"))
                        insert = insert + alist.get(i).get(j).trim();
                    else 
                        insert = insert + "'" + alist.get(i).get(j).trim() + "'";
                }                   
                else
                {
                    if(((StringUtils.isStrictlyNumeric(alist.get(i).get(j).trim()))) || (alist.get(i).get(j).trim().contains("null")))
                        insert = insert +","+ alist.get(i).get(j).trim();
                    else 
                        insert = insert + ",'" + alist.get(i).get(j).trim() + "'";      
                }

            }
            if(i < alist.size()-1)
                insert= insert +"),";
            else 
                insert= insert +")";
            insert = insert +"\r";

        }

        //System.out.println(insert);
        return insert;

    }

在这里,我遍历了整个列表并将值添加到一个字符串中,以便我可以使用该字符串进行插入。 我将文件名用作表名,并将文件的第一行用作插入中的列。 所有其他行都是值。

完成这一步后,我得到了这样一个字符串 "REPLACE INTO tablename (column1,column2 ... columnx) 值(值 1,值 2 ... 值 x), (值 1,值 2 ... 值 x), ……”

现在我将使用该字符串执行我的 InsertInDb 类,是的,就是这样。

但是第二步太花时间了。 (我现在等了一个小时) 有没有更聪明的方法来做我想做的事? (在我们的数据库中自动插入所有 CSV)

BigList 会提高速度吗? https://dzone.com/articles/biglist-scalable-high (现在无法测试)

编辑: 我为解决问题所做的工作:

我为我的 SQL 语句创建了一个类 -->

public class BuildInsert {


    private String insertString;

    public String getINSERTSTRING()
    {
        return insertString;
    }

    BuildInsert(String tablename, List<String> alist )
    {   
        int size = alist.size();

        this.insertString = "REPLACE INTO " + tablename + "(";

        // Insert "Header"
        for(int j=1; j <= size ;j++) 
        {
            if(j < size)
                this.insertString = this.insertString + alist.get(j-1)+",";
            else
                this.insertString = this.insertString + alist.get(j-1)+")\n";

        }

        this.insertString = this.insertString +"VALUES(";

        // Insert values
        for(int j=1; j <= size ;j++) 
        {
            if(j < size)
                this.insertString = this.insertString + "?,";
            else
                this.insertString = this.insertString + "?)";

        }
    }

}

并像 Mike 提到的那样为批量插入/准备好的语句勾选这个字符串:

Connection con;
        Statement stmt;

        final int batchSize = 1000;
        int count = 0;

        int sizeH = alist.size();
        int sizeL = alist.get(0).size();

        try {

             // Connection oeffnen und prepared statment vorbereiten
            System.out.println("Connecting to database...");
            con = DriverManager.getConnection(DB_URL,USER,PASS);
            con.setAutoCommit(false);

            ps = con.prepareStatement(insertString);

            stmt = con.createStatement();

          //< alist.size()
            for(int i=1;i < sizeH ;i++) // Size nach "unten" 
            {
                for(int j=0; j < sizeL;j++) // Size nach "rechts" 
                {
                    ps.setString(j+1, alist.get(i).get(j));
                }

                ps.addBatch();

                if(++count % batchSize == 0){
                    ps.executeBatch();
                    con.commit();
                }
            }    

            ps.executeBatch();
            con.commit();

        }

插入现在快多了。 (110 万行约 230 瑞典克朗)

谢谢你们;-)

最佳答案

Now, that I have the List in the format I need, I would like to create a Insert out of it, so we can import the data in our database.

不要那样做!做一个 JDBC batch insert反而。 (参见 this 了解如何执行 PreparedStatement,这将为您在格式化插入语句时省去很多麻烦)

关于Java - 有一个巨大的 ArrayList(超过 100 万),如何在可接受的时间内创建它的 String?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38826672/

相关文章:

php - 播放mysql数据库中存储的声音文件

php - 如何使登录页面 PHP 与 Session 一起工作。

r - 如何为 R 中散点图中的类赋予颜色?

php - 如何在 PHP 中解析列中具有多行数据的 csv

java - 如何使 Eclipse 中 Java 8 lambda 参数的代码完成工作?

java - Apache Commons AsyncClient - 忽略证书 - SSLPeerUnverifiedException

java - "VK_..."keyCodes 是方法还是对象?

java - 将当前目录添加到 JAR 文件的类路径

javascript - 如何在mysql中成功插入数据后显示警告框?

Mysql插入包含双逗号的值