Java,内存使用量为;扫描器;
我正在运行一个在线自动程序评估平台,其中一个练习中,Java“扫描器”使用的内存太多(我们刚刚开始支持Java,所以以前没有出现过这个问题)。当我们向初学者教授算法时,我们不能要求他们通过逐个读取字节来重新编码 根据我们的测试,扫描仪最多使用200字节读取一个整数 练习:10000个整数,100个连续整数的哪个窗口的和最大 内存使用量很小(您只需要记住最后100个整数),但是在带有“Scanner/nextInt()”的经典版本和手动版本(见下文)之间,我们可以看到内存中有2.5 Mb的差异 2.5 Mb读取10000个整数==>200字节读取一个整数 有没有什么简单的解决方案可以向初学者解释,或者下面的函数(或类似的函数)是一种方法Java,内存使用量为;扫描器;,java,memory,io,java.util.scanner,Java,Memory,Io,Java.util.scanner,我正在运行一个在线自动程序评估平台,其中一个练习中,Java“扫描器”使用的内存太多(我们刚刚开始支持Java,所以以前没有出现过这个问题)。当我们向初学者教授算法时,我们不能要求他们通过逐个读取字节来重新编码 根据我们的测试,扫描仪最多使用200字节读取一个整数 练习:10000个整数,100个连续整数的哪个窗口的和最大 内存使用量很小(您只需要记住最后100个整数),但是在带有“Scanner/nextInt()”的经典版本和手动版本(见下文)之间,我们可以看到内存中有2.5 Mb的差异 2
我们的测试函数可以更快地读取整数,同时使用更少的内存:
public static int read_int() throws IOException
{
int number = 0;
int signe = 1;
int byteRead = System.in.read();
while (byteRead != '-' && ((byteRead < '0') || ('9' < byteRead)))
byteRead = System.in.read();
if (byteRead == '-'){
signe = -1;
byteRead = System.in.read();
}
while (('0' <= byteRead) && (byteRead <= '9')){
number *= 10;
number += byteRead - '0';
byteRead = System.in.read();
}
return signe*number;
}
public static int read_int()引发IOException
{
整数=0;
int符号=1;
int byteRead=System.in.read();
while(byteRead!='-'&&((byteRead<0')| |('9' while(('0'这是来自Scanner的nextInt()的代码
public int nextInt(int radix) {
// Check cached result
if ((typeCache != null) && (typeCache instanceof Integer)
&& this.radix == radix) {
int val = ((Integer)typeCache).intValue();
useTypeCache();
return val;
}
setRadix(radix);
clearCaches();
// Search for next int
try {
String s = next(integerPattern());
if (matcher.group(SIMPLE_GROUP_INDEX) == null)
s = processIntegerToken(s);
return Integer.parseInt(s, radix);
} catch (NumberFormatException nfe) {
position = matcher.start(); // don't skip bad token
throw new InputMismatchException(nfe.getMessage());
}
}
如您所见,它是基数和符号感知的,使用缓存等。因此,额外的内存使用全部来自于旨在提高扫描仪效率的功能。您可以将所有值读取到数组中,然后开始对数组求和
在读取数组时,您仍然需要那么多内存,但在读取之后,它就可以用于其他目的了
imho,代码的结构将受益匪浅,因为现在您可以使用不同的数字源-例如util.Random,仍然可以搜索数组中的最大和,或者搜索相同数组中的不同序列长度,而无需重新读取输入
顺便说一句:我很难阅读代码,因为:
- value/values/sumValues/nb_values-(为什么不是maximumValues)?-所有变量都是值,因此这无助于理解
- 循环通常使用i和j或n进行索引。值具有误导性
- 长度\序列也有误导性。序列长度是指长度,但每个人都只会使用“长度”,因为它与其他长度无关
- 对于琐碎的事情,你使用长名称,但对于不那么琐碎的事情,你使用一个神秘的缩写。我阅读了你的问题描述和代码,不知道你的代码是什么:你所说的nb_值是什么意思。非阻塞?空字节?附近?它是什么
我的第一印象是,对于一系列INT:
3 9 2 4 6 4 3 2 4 4 5 6 9 3 2 1 9 9 9
您可以搜索长度为3到第9个值的序列(不包括3和9本身),并搜索最大值(2+4+6),(4+6+4),…(4+4+5),但结果是34。
将前9个值相加
建议:
import java.util.Scanner;
class MaxChunk {
int chunksize;
public int[] readValues () {
Scanner sc = new Scanner (System.in);
chunksize = sc.nextInt ();
int length = sc.nextInt ();
int values[] = new int [length];
for (int i = 0; i < length; i++)
{
values[i] = sc.nextInt();
}
return values;
}
public int calc (int values[]) {
int sum = 0;
for (int i = 0; i < chunksize; i++)
{
sum += values[i];
}
int maximum = sum;
for (int j = chunksize; j < values.length; j++)
{
sum -= values [j - chunksize];
sum += values [j];
if (maximum < sum)
maximum = sum;
}
return maximum;
}
public static void main (String[] args) {
MaxChunk maxChunk = new MaxChunk ();
int values[] = maxChunk.readValues ();
System.out.println (maxChunk.calc (values));
}
}
echo "3 9 2 4 6 4 3 2 4 4 5 6 9 3 2 1 9 9" | java MaxChunk
import java.util.Scanner;
类MaxChunk{
整数块大小;
公共int[]读取值(){
扫描仪sc=新的扫描仪(System.in);
chunksize=sc.nextInt();
int length=sc.nextInt();
int值[]=新的int[长度];
for(int i=0;i
产量14。我们最终决定重新编写(部分)Scanner类。这样,我们只需要包含我们的Scanner而不是Java的Scanner,其余的代码保持不变。我们不再有任何内存问题,程序速度快了20倍
下面的代码来自我的同事Christoph Dürr:
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
class Locale {
final static int US=0;
}
public class Scanner {
private BufferedInputStream in;
int c;
boolean atBeginningOfLine;
public Scanner(InputStream stream) {
in = new BufferedInputStream(stream);
try {
atBeginningOfLine = true;
c = (char)in.read();
} catch (IOException e) {
c = -1;
}
}
public boolean hasNext() {
if (!atBeginningOfLine)
throw new Error("hasNext only works "+
"after a call to nextLine");
return c != -1;
}
public String next() {
StringBuffer sb = new StringBuffer();
atBeginningOfLine = false;
try {
while (c <= ' ') {
c = in.read();
}
while (c > ' ') {
sb.append((char)c);
c = in.read();
}
} catch (IOException e) {
c = -1;
return "";
}
return sb.toString();
}
public String nextLine() {
StringBuffer sb = new StringBuffer();
atBeginningOfLine = true;
try {
while (c != '\n') {
sb.append((char)c);
c = in.read();
}
c = in.read();
} catch (IOException e) {
c = -1;
return "";
}
return sb.toString();
}
public int nextInt() {
String s = next();
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
return 0; //throw new Error("Malformed number " + s);
}
}
public double nextDouble() {
return new Double(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public void useLocale(int l) {}
}
import java.io.BufferedInputStream;
导入java.io.IOException;
导入java.io.InputStream;
类区域设置{
最终静态int US=0;
}
公共类扫描仪{
私有缓冲输入流;
INTC;
布尔型的起始点;
公共扫描仪(输入流){
in=新的BufferedInputStream(流);
试一试{
AtBeginngofline=true;
c=(char)in.read();
}捕获(IOE异常){
c=-1;
}
}
公共布尔hasNext(){
如果(!AtBeginngofline)
抛出新错误(“hasNext仅起作用”+
“致电nextLine后”);
返回c!=-1;
}
公共字符串next(){
StringBuffer sb=新的StringBuffer();
AtBeginngofline=假;
试一试{
而(c)"{
sb.附加((char)c);
c=in.read();
}
}捕获(IOE异常){
c=-1;
返回“”;
}
使某人返回字符串();
}
公共字符串nextLine(){
StringBuffer sb=新的StringBuffer();
AtBeginngofline=true;
试一试{
而(c!='\n'){
sb.附加((char)c);
c=in.read();
}
c=in.read();
}捕获(IOE异常){
c=-1;
返回“”;
}
使某人返回字符串();
}
public int nextInt(){
字符串s=next();
试一试{
返回整数.parseInt;
}捕获(数字格式){
返回0;//抛出
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
class Locale {
final static int US=0;
}
public class Scanner {
private BufferedInputStream in;
int c;
boolean atBeginningOfLine;
public Scanner(InputStream stream) {
in = new BufferedInputStream(stream);
try {
atBeginningOfLine = true;
c = (char)in.read();
} catch (IOException e) {
c = -1;
}
}
public boolean hasNext() {
if (!atBeginningOfLine)
throw new Error("hasNext only works "+
"after a call to nextLine");
return c != -1;
}
public String next() {
StringBuffer sb = new StringBuffer();
atBeginningOfLine = false;
try {
while (c <= ' ') {
c = in.read();
}
while (c > ' ') {
sb.append((char)c);
c = in.read();
}
} catch (IOException e) {
c = -1;
return "";
}
return sb.toString();
}
public String nextLine() {
StringBuffer sb = new StringBuffer();
atBeginningOfLine = true;
try {
while (c != '\n') {
sb.append((char)c);
c = in.read();
}
c = in.read();
} catch (IOException e) {
c = -1;
return "";
}
return sb.toString();
}
public int nextInt() {
String s = next();
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
return 0; //throw new Error("Malformed number " + s);
}
}
public double nextDouble() {
return new Double(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public void useLocale(int l) {}
}
4047 4102 char[] 13 java.lang.AbstractStringBuilder enlargeBuffer
4045 3070 char[] 13 java.lang.String <init>
4085 2834 char[] 13 java.lang.AbstractStringBuilder enlargeBuffer
4048 2738 char[] 13 java.lang.AbstractStringBuilder enlargeBuffer
4099 1892 char[] 13 java.lang.AbstractStringBuilder enlargeBuffer
4108 1264 char[] 13 java.lang.AbstractStringBuilder enlargeBuffer
4118 1222 char[] 13 java.lang.AbstractStringBuilder enlargeBuffer
4041 1128 int[] 13 java.util.regex.Matcher usePattern
[...]