gpt4 book ai didi

java - 我可以使用什么数据结构或设计模式来解决这个问题

转载 作者:行者123 更新时间:2023-12-01 09:21:20 25 4
gpt4 key购买 nike

我有以下设计问题,希望得到您的帮助解决。下面是代码的简单介绍

class DataProcessor{
public List<Record> processData(DataFile file){
List<Record> recordsList = new ArrayList<Record>();
for(Line line : file.getLines()){
String processedData = processData(line);
recordsList.add(new Record(processedData));
}
}

private String processData(String rawLine){
//code to process line
}
}
class DatabaseManager{
saveRecords(List<Record> recordsList){
//code to insert records objects in database
}
}
class Manager{
public static void main(String[] args){

DatabaseManager dbManager = new DatabaseManager("e:\\databasefile.db");
DataFile dataFile = new DataFile("e:\\hugeRawFile.csv");
DataProcessor dataProcessor = new DataProcessor();
dbManager.saveRecords(dataProcessor.processData(dataFile));
}
}

如您所见,“DataProcessor”类的“processData”方法采用 DataFile 对象,处理整个文件,为每一行创建 Record 对象,然后返回“Record”对象的列表。

“processData”方法的问题:当原始文件非常大时,“记录列表”对象会占用大量内存,有时程序会失败。我需要更改当前的设计,以使内存使用量最小化。 “DataProcessor”不应直接访问“DatabaseManager”。我正在考虑将队列传递给“processData”方法,其中一个线程运行“processData”方法以将“Record”对象插入队列中,而另一个线程从队列中删除“Record”对象并将其插入数据库中。但我不确定这样做的性能问题。

最佳答案

将驱动流程的责任放入最受约束的资源(在您的情况下是DataProcessor) - 这将确保最好地遵守约束,而不是被迫达到临界点。

注意:甚至不要考虑多线程,它对处理文件没有任何好处。如果您的数据通过网络传输,当您不知道下一个数据 block 何时到达时,线程将是一个解决方案,也许您可​​以利用 CPU 时间做更好的事情,而不是等待“直到牛回家栖息” ”(咧嘴笑)。但是有文件吗?你知道这项工作有开始和结束,所以尽快开始吧。

class DataProcessor{
public List<Record> processData(DataFile file){
List<Record> recordsList = new ArrayList<Record>();
for(Line line : file.getLines()){
String processedData = processData(line);
recordsList.add(new Record(processedData));
}
}

private String processData(String rawLine){
//code to process line
}

public void processAndSaveData(DataFile dataFile, DatabaseManager db) {
int maxBuffSize=1024;
ArrayList<Record> buff=new ArrayList<Record>(maxBuffSize);
for(Line line : file.getLines()){
String processedData = processData(line);
buff.add(new Record(processedData));
if(buff.size()==maxBuffSize) {
db.saveRecords(buff);
buff.clear();
}
}
// some may be still unsaved here, less that maxBuffSize
if(buff.size()>0) {
db.saveRecords(buff);
// help the CG, let it recycle the records
// without needing to look "is buff still reacheable"?
buff.clear();
}
}
}

class Manager{
public static void main(String[] args){

DatabaseManager dbManager = new DatabaseManager("e:\\databasefile.db");
DataFile dataFile = new DataFile("e:\\hugeRawFile.csv");
DataProcessor dataProcessor = new DataProcessor();

// So... do we need another stupid manager to tell us what to do?
// dbManager.saveRecords(dataProcessor.processData(dataFile));

// Hell, no, the most constrained resource knows better
// how to deal with the job!
dataProcessor.processAndSaveData(dataFile, dbManager);
}
}

[编辑]解决“但我们已经确定了内容和方式,现在您来告诉我们需要编写额外的代码?”

构建一个 AbstractProcessor 类并要求您的伙伴从它派生。

class AbstractProcessor {
// sorry, need to be protected to be able to call it
abstract protected Record processData(String rawLine);

abstract protected Class<? extends Record> getRecordClass();

public void processAndSaveData(DataFile dataFile, DatabaseManager db) {
Class<? extends Record> recordType=this.getRecordClass();
if(recordType.equals(MyRecord1.class) {
// buffered read and save MyRecord1 types specifically
}
else if(recordType.equals(YourRecord.class)) {
// buffered read and save YourRecord types specifically
}
// etc...
}
}

现在,他们需要做的就是“编码”extends AbstractProcessor 并使其 processData(String) 受到保护,并编写一个简单的方法来声明其记录类型(可能也可以是一个枚举)。这并不是说您要求他们付出巨大的努力,并使本来成本高昂(对于 TB 输入文件来说甚至不可能)的操作变成“尽可能快的操作”。

关于java - 我可以使用什么数据结构或设计模式来解决这个问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40147851/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com