Ваш файл содержит 200'000 строк, но ваш 2D-массив имеет 259'361'616 ячеек, и размер StringBuilder
будет пропорционален этому числу. Вам не нужно хранить все это: это очень пустая матрица.
Вот что я бы сделал: читая входной файл, я построил бы два набора строк: элементы и пользователи, и картуприсвоение рейтинга каждой паре (элемент, пользователь):
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
s, чтобы убедиться, что элементы отсортированы, но если вас это не волнует, вы можетевместо этого используйте HashSet
s. Чтобы сохранить элементы в порядке их появления, как вы делаете в своем коде, вы можете использовать LinkedHashSet
s.
Затем вы можете записать в выходной файл, например:
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);
}
ОБНОВЛЕНИЕ:
В случае, когда у вас есть более одного рейтинга для одной и той же пары (предмет, пользователь), вы сохраняете только последний. Вы можете рассчитать среднее значение, используя 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
не пропорционаленк размеру матрицы, но к количеству элементов, умноженному на количество пользователей.