正如我提到的,我有这种格式的大量 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/