Stack Overflow на русском Asked by ForsaiR on January 27, 2021
Имеется задача: в строке файла имеется 3 значения, найти их среднее и вывести минимальное значение из всех строк в файле.
Вся проблема заключается в том – как считать эти данные вообще? Уже при попытке считать пару гигов все крашится и выпадает ошибка нехватки памяти. И возможно ли это сделать это за оптимальное время?
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class Solution {
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
FileInputStream fileInputStream = new FileInputStream(reader.readLine());
reader.close();
int[] arrayPoint = new int[3];
int size = 65536;
int bufferSize = size;
byte buffer[] = new byte[size];
while (fileInputStream.available() > 0) {
if (fileInputStream.available() < size) bufferSize = fileInputStream.available();
fileInputStream.read(buffer, 0, bufferSize);
byte[] byteArray = new byte[1];
int byteArraySize = 0;
byte pointArraySize = 0;
for(int i = 0; i < bufferSize; i += 1) {
if (buffer[i] == 0x20) {
if (byteArraySize > 0) {
try {
arrayPoint[pointArraySize] = byteArrayToInt(byteArray);
pointArraySize += 1;
if (pointArraySize > 3) {
search(arrayPoint);
arrayPoint = new int[3];
pointArraySize = 0;
}
byteArray = new byte[1];
byteArraySize = 0;
} catch (Exception e) {
byteArray = new byte[1];
arrayPoint = new int[3];
byteArraySize = 0;
pointArraySize = 0;
}
}
} else if ((buffer[i] == 0x2D) || ((buffer[i] > 0x2F) && (buffer[i] < 0x3A))) {
byteArraySize += 1;
//тут возникли проблемы со считыванием нескольких чисел и больших
//в основном с byteArray
}
}
}
}
public static void search(int[] points) {
//тут поиск среднего, в принципе есть, но пока пусть глаза не мазолит
}
public static int byteArrayToInt(byte[] byteArray) {
int value = byteArray[byteArray.length - 1] - 48;
int count = 10;
for (int i = byteArray.length - 2; i >= 0; i -= 1) {
if (byteArray[i] != 45) {
value += (byteArray[i] - 48) * count;
count *= 10;
} else {
value *= -1;
}
}
return value;
}
}
Решение на Java 8 Stream Api
public class Solution {
private static final String SPACE = " ";
public static void main(String[] args) {
// оборачиваем в try-with-resources чтобы избежать проблем с закрытием Scanner
try (Scanner scanner = new Scanner(System.in)) {
// Сканируем одну строку и получаем из нее путь к файлу
Double minValueFromBufferedReader = getMinValueFromFile(scanner.nextLine());
//TODO: сделать что-то со значением
} catch (IOException e) {
// TODO: ошибки чтения, файл заблокирован, не существует, и т.п.
e.printStackTrace();
}
}
private static Double getMinValueFromFile(String filePath) throws IOException {
// оборачиваем в try-with-resources чтобы избежать проблем с закрытием файла
try (Stream<String> lines = Files.lines(Paths.get(filePath))) {
return lines
//разделяем значения в строке и возвращаем минимальное из них
.mapToDouble(Solution::splitWithSpaceAndReturnMin)
//сравниваем минимальные значения строк и возвращаем минимальное из них
.min()
//если таких нет - возвращаем максимальное значение
.orElse(Double.MAX_VALUE);
}
}
private static Double splitWithSpaceAndReturnMin(String currentLine) {
// разделяем строку на 3 значения, разделенные пробелами и помещаем в массив
String[] numbersAsString = currentLine.split(SPACE, 3);
return Arrays.stream(numbersAsString)
// превращаем строки в числа с плавающей точкой (Double)
.mapToDouble(Double::parseDouble)
//находим среднее из них
.average()
//если таких нет - вернуть максимально возможное значение
.orElse(Double.MAX_VALUE);
}
}
Correct answer by Nalmelune on January 27, 2021
Я бы предложил не заниматься парсингом в ручную и переложить всю работу на стандартную библиотеку.
double min = Double.MAX_VALUE;
Scanner r = new Scanner(System.in);
while (r.hasNextInt()) {
int a = r.nextInt();
int b = r.nextInt();
int c = r.nextInt();
double average = (a + b + c) / 3.;
min = Math.min(min, average);
}
System.out.println("min = " + min);
Answered by talex on January 27, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP