gpt4 book ai didi

java - Java 上的堆内存问题

转载 作者:行者123 更新时间:2023-11-30 01:45:22 25 4
gpt4 key购买 nike

我正在尝试运行下面的程序,但在 StringBuilder 附加循环结构期间出现 OutOfMemory 错误。

  1. 我正在尝试采取任何措施来降低内存使用量,使其足以读取 CSV 文件(超过 200,000 行,但只有 3 列:项目、评级、用户)。
  2. 然后我将创建一个 2D int 数组,其中唯一的项目代表行,唯一用户代表列,交集是评级。
  3. 最后,我将使用 StringBuilder 来帮助创建输出 CSV 文件

感谢您的帮助和时间。

      List<String> userList = new ArrayList<String>();
List<String> itemList = new ArrayList<String>();


FileInputStream stream = null;
Scanner scanner = null;
int[][] layout = new int[10672][24303];

int indexItemList = 0;
double temp = 0;

try{
stream = new FileInputStream(fileName);
scanner = new Scanner(stream, "UTF-8");
while (scanner.hasNextLine()){
String line = scanner.nextLine();
if (!line.equals("")){
String[] elems = line.split(",");
if (indexItemList == 0) {
temp = Double.valueOf(elems[1]);
layout[0][0] = (int)temp;
itemList.add(elems[0]);
userList.add(elems[2]);
indexItemList++;
}
else {
boolean itemFound = itemList.contains(elems[0]);
boolean userFound = userList.contains(elems[2]);

int indexItem = 1;
int indexUser = 1;
if ((itemFound) && (userFound)) {
indexItem = itemList.indexOf(elems[0]);
indexUser = userList.indexOf(elems[2]);
temp = Double.valueOf(elems[1]);
layout[indexItem][indexUser] = (int)temp;
}
else if ((itemFound) && (!userFound)) {
userList.add(elems[2]);
indexItem = itemList.indexOf(elems[0]);
indexUser = userList.indexOf(elems[2]);
temp = Double.valueOf(elems[1]);
layout[indexItem][indexUser] = (int)temp;
}
else if ((!itemFound) && (userFound)){
itemList.clear();
itemList.add(elems[0]);
indexUser = userList.indexOf(elems[2]);
temp = Double.valueOf(elems[1]);
layout[indexItemList][indexUser] = (int)temp;
indexItemList++;
}
else if (!((itemFound) && (userFound))) {
itemList.clear();
itemList.add(elems[0]);
userList.add(elems[2]);
indexUser = userList.indexOf(elems[2]);
temp = Double.valueOf(elems[1]);
layout[indexItem][indexUser] = (int)temp;
indexItemList++;
}
}
}
}
if (scanner.ioException() != null){
throw scanner.ioException();
}
}
catch (IOException e){
System.out.println(e);
}
finally{
try{
if (stream != null){
stream.close();
}
}
catch (IOException e){
System.out.println(e);
}
if (scanner != null){
scanner.close();
}
}

StringBuilder sb = new StringBuilder();

for (int i = 0; i < layout.length; i++){
for (int j = 0; j < layout[i].length; j++){
sb.append(layout[i][j] + "");
layout[i][j] = 0;
if (j < layout[i].length - 1){
sb.append(",");
}
}
sb.append("\n");
}

最佳答案

您的文件有 200'000 行,但您的二维数组有 259'361'616 个单元格,StringBuilder 的大小将与该数字成正比。您不需要存储所有这些:它是一个非常空心的矩阵。

这就是我要做的:在读取输入文件时,我将构建两个字符串集:项目和用户,以及将评级与每个(项目,用户)对关联的 map :

    Set<String> items = new TreeSet<>();
Set<String> users = new TreeSet<>();
Map<String,Double> ratings = new HashMap<>();
try (InputStream stream = new FileInputStream(fileName);
Scanner scanner = new Scanner(stream, "UTF-8")) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (!line.equals("")) {
String[] elems = line.split(",");
String item = elems[0];
String user = elems[2];
double rating = Double.parseDouble(elems[1]);
items.add(item);
users.add(user);
ratings.put(item+','+user, rating);
}
}
} catch (IOException e) {
System.out.println(e);
}

请注意,我使用了 TreeSet 来确保元素已排序,但如果您不关心这一点,则可以使用 HashSet 来代替。为了保持元素的出现顺序,正如您在代码中所做的那样,您可以使用 LinkedHashSets。

然后您可以像这样写入输出文件:

    try (OutputStream stream = new FileOutputStream(outputName);
Writer writer = new OutputStreamWriter(stream, "UTF-8");
PrintWriter out = new PrintWriter(writer)) {
for (String item: items) {
int j = 0;
for (String user: users) {
Double rating = ratings.get(item+','+user);
double r = rating == null ? 0 : rating;
out.print(r);
++j;
if (j < users.size()) {
out.print(',');
}
}
out.println();
}
} catch (IOException e) {
System.out.println(e);
}

更新:

如果您对同一对(项目、用户)有多个评分,则仅保留最后一个。您可以在 map 中使用 Accumulator 而不是 Double 来计算平均值:

public class Accumulator {
private int count;
private double sum;

public void add(double value) {
sum += value;
++count;
}

public double getAverage() {
return count == 0 ? 0 : sum/count;
}
}

更新 2:勘误表

StringBuilder 的大小与矩阵的大小不成正比,而是与项目数乘以用户数成正比。

关于java - Java 上的堆内存问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58229998/

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