문자열 테이블을 한 형식에서 다른 형식으로 변환하는 작업이 있습니다. 테이블 변환 알고리즘의 속도를 향상시키는 방법은 무엇입니까?
나는 테이블 변환이 클래스를 사용
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
class TableConverter
{
public String[] Entities; //here I store descriptive fields like DescField1, DescField2...
public ArrayList<String> ConvertedList; //here I store converted table rows as separate string lines
public TableConverter(ArrayList<String> lines) //we receive table rows as separate string lines
{
String[] splitted_first_line = lines.get(0).split("\t"); //split first row to get descriptive fields
this.Entities = new String[splitted_first_line.length - 2]; //allocate size to hold all descriptive fields. -2 because last two columns is Date and Total
System.arraycopy(splitted_first_line, 0, this.Entities, 0, this.Entities.length); //copy descriptive fields into my arr
//--
int lines_sz = lines.size(); //save lines size to not recalculate it every iteration
Map<String, Integer> k_d_map = new HashMap<String, Integer>(); //map to store indecies of every Date column
for (int i = 1; i < lines_sz; i++)
{
if (lines.get(i).isEmpty())
continue;
String[] splitted_line = lines.get(i).split("\t"); //splitted line on values
if (!k_d_map.containsKey(splitted_line[splitted_line.length - 2])) //if my map does not contain such date
k_d_map.put(splitted_line[splitted_line.length - 2], 0); //then add it
}
String[] known_dates = k_d_map.keySet().toArray(new String[k_d_map.size()]);
SortStrDates(known_dates); //I sort dates by ASC
k_d_map.clear(); //clear map to fill it again with correct indecies
for (int i = 0; i < known_dates.length; i++) //refilling map and now we know every date index
k_d_map.put(known_dates[i], i);
//--
Map<String, EntitySales> ESs_map = new HashMap<String, EntitySales>(); //map for rows
for (int i = 1; i < lines_sz; i++)
{
if (lines.get(i).isEmpty())
continue;
String[] splitted_line = lines.get(i).split("\t"); //split row
String curr_entity = GetEntityFromLine(splitted_line); //I get set of descriptive fields separated by \t. It looks like this: asd\tqwe\t...\tzxc
int dti = k_d_map.get(splitted_line[splitted_line.length - 2]); //I get date column index for Date stored in this row (if it was 02.2017 then index will be 0)
if (ESs_map.containsKey(curr_entity)) //I check if map contains row with such descriptive fields set
ESs_map.get(curr_entity).SalesAmounts[dti] = splitted_line[splitted_line.length - 1]; //if contains, we set sale amount at date index (set 5 to 02.2017 column for example)
else
{
EntitySales es = new EntitySales(curr_entity, known_dates.length); //else we create new object to hold row
es.SalesAmounts[dti] = splitted_line[splitted_line.length - 1]; //set sales amount at date
ESs_map.put(curr_entity, es); //and add to map
}
}
//--
String first_row = ""; //here and below I build first row text representation, I add stored DescFields and unique dates
this.ConvertedList = new ArrayList<String>();
for (int i = 0; i < this.Entities.length; i++)
first_row += this.Entities[i] + "\t";
for (int i = 0; i < known_dates.length; i++)
first_row += i < known_dates.length - 1 ? known_dates[i] + "\t" : known_dates[i];
this.ConvertedList.add(first_row);
//--
for (EntitySales es : ESs_map.values()) //Here I get rows as separate lines
this.ConvertedList.add(es.GetAsLine());
}
public String GetEntityFromLine(String[] line)
{
String[] entities = new String[line.length - 2];
System.arraycopy(line, 0, entities, 0, entities.length);
String entity = "";
for (int i = 0; i < entities.length; i++)
entity += i < entities.length - 1 ? entities[i] + "\t" : entities[i];
return entity;
}
public void SortStrDates(String[] dates)
{
for (int i = 0; i < dates.length; i++)
for (int j = i + 1; j < dates.length; j++)
{
Date dt_i = MyJunk.ConvertStrToDate(dates[i]);
Date dt_j = MyJunk.ConvertStrToDate(dates[j]);
if (dt_j.before(dt_i))
{
String temp_i = dates[i];
dates[i] = dates[j];
dates[j] = temp_i;
}
}
}
}
class EntitySales
{
public String Entity;
public String[] SalesAmounts;
public EntitySales(String entity, int sales_amounts_size)
{
this.Entity = entity;
this.SalesAmounts = new String[sales_amounts_size];
}
public String GetAsLine()
{
String line = this.Entity + "\t";
for (int i = 0; i < this.SalesAmounts.length; i++)
{
String val = this.SalesAmounts[i] == null || this.SalesAmounts[i].isEmpty() ? "0" : this.SalesAmounts[i];
line += i < this.SalesAmounts.length - 1 ? val + "\t" : val;
}
return line;
}
}
그것은 작동하지만, 큰 테이블이 느린 궁극적. 나는 800k 행 테이블과 취소 된 작업을 변환하기 위해 1 시간 20 분을 기다렸다. 200k 개의 행이 3 분 안에 변환됩니다. 내가 왜 그런 둔화를 겪었는지 모르겠다.하지만 문제는 내 알고리즘을 많이 빠르게하는 방법이다. 설명 필드 (asd \ tqwe \ t ... \ tzxc -> 0, something \ telse -> 1)의 모든 집합에 Integer
값을 할당하고 Maps
없이 해당 정수를 비교하려고 시도했지만 속도가 느려졌습니다. 당신이 당신의 전반적인 알고리즘을 개선 할 수있는 반면
작은 개선 사항 : for 루프 내에 문자열 및 문자열 배열을 선언하지 마십시오. 예를 들어, TableConverter 메소드에서'String [] splitted_line'을 한 번만 delcare하여 2 for for 루프에서 사용할 수 있습니다. – StephaneM
@StephaneM - 알았어, 고마워, 슬프게도 나는 모든 일을 너무 빨리 할 수 있다고 생각하지 않는다. – Kosmos
프로파일 러의 감독하에 코드를 실행하는 데 소요되는 시간을 이해하는 데 도움이 될 수 있습니다. – fvu