Java中的ArrayList和输入
我已经习惯了python,所以这让我有些困惑。我试图逐行接受输入,直到用户输入特定数字为止。这些数字将存储在数组中,以对它们应用一些统计数学。目前,我有一个主类,一个stats类和一个" reading"类。
两个问题:
- 我似乎无法解决输入循环问题,这样做的最佳实践是什么。
- 如何防止数组中存储超过1000个值?
让我展示一下我到目前为止所拥有的:
public static java.util.ArrayList readRange(double end_signal){
//read in the range and stop at end_signal
ArrayList input = new ArrayList();
Scanner kbd = new Scanner( System.in );
int count = 0;
do{
input.add(kbd.nextDouble());
System.out.println(input); //debugging
++count;
} while(input(--count) != end_signal);
return input;
}
任何帮助将不胜感激,原谅我的新手...
解决方案
在循环条件中需要的是:
while ( input.get( input.size()-1 ) != end_signal );
我们正在做的是递减计数器变量。
你也应该像这样声明ArrayList:
ArrayList<Double> list = new ArrayList<Double>();
这使得列表类型特定,并允许给出条件。否则会有额外的转换。
**
public static java.util.ArrayList readRange(double end_signal) {
//read in the range and stop at end_signal
ArrayList input = new ArrayList();
Scanner kbd = new Scanner(System. in );
int count = 0;
do {
input.add(Double.valueOf(kbd.next()));
System.out.println(input); //debugging
++count;
} while (input(--count) != end_signal);
return input;
}
**
答案:
- 我似乎无法解决输入循环问题,这样做的最佳实践是什么。
我宁愿有一个简单的while循环,而不是do {} while ...并将条件放入while ...在我的示例中为:
当读取的数字不是结束信号并且计数低于限制时:执行。
- 读取方法的对象类型是什么?一个double []还是一个ArrayList?
ArrayList,但是我强烈建议我们使用List(java.util.List)接口代替。对接口进行编程而不是对实现进行编程是一种好的OO实践。
2.1如何声明method-type为arraylist?
请参见下面的代码。
2.2. 如何防止数组中存储超过1000个值?
通过在while条件中添加此限制。
import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
public class InputTest{
private int INPUT_LIMIT = 10000;
public static void main( String [] args ) {
InputTest test = new InputTest();
System.out.println("Start typing numbers...");
List list = test.readRange( 2.0 );
System.out.println("The input was " + list );
}
/**
* Read from the standar input until endSignal number is typed.
* Also limits the amount of entered numbers to 10000;
* @return a list with the numbers.
*/
public List readRange( double endSignal ) {
List<Double> input = new ArrayList<Double>();
Scanner kdb = new Scanner( System.in );
int count = 0;
double number = 0;
while( ( number = kdb.nextDouble() ) != endSignal && count < INPUT_LIMIT ){
System.out.println( number );
input.add( number );
}
return input;
}
}
最后说明:
与类方法相比,最好具有"实例方法"。这样,如果需要,可以由子类处理" readRange"而不必更改签名,因此在示例中,我删除了" static"关键字,并创建了" InputTest"类的实例
在Java代码样式中,变量名称应使用cammel格式,例如" endSignal"而不是" end_signal"
我认为我们起步不错,但这是我的建议。我将在代码下面突出显示重要的区别和要点:
软件包控制台;
导入java.util .;
导入java.util.regex。
公共类ArrayListInput {
public ArrayListInput() {
// as list
List<Double> readRange = readRange(1.5);
System.out.println(readRange);
// converted to an array
Double[] asArray = readRange.toArray(new Double[] {});
System.out.println(Arrays.toString(asArray));
}
public static List<Double> readRange(double endWith) {
String endSignal = String.valueOf(endWith);
List<Double> result = new ArrayList<Double>();
Scanner input = new Scanner(System.in);
String next;
while (!(next = input.next().trim()).equals(endSignal)) {
if (isDouble(next)) {
Double doubleValue = Double.valueOf(next);
result.add(doubleValue);
System.out.println("> Input valid: " + doubleValue);
} else {
System.err.println("> Input invalid! Try again");
}
}
// result.add(endWith); // uncomment, if last input should be in the result
return result;
}
public static boolean isDouble(String in) {
return Pattern.matches(fpRegex, in);
}
public static void main(String[] args) {
new ArrayListInput();
}
private static final String Digits = "(\p{Digit}+)";
private static final String HexDigits = "(\p{XDigit}+)";
// an exponent is 'e' or 'E' followed by an optionally
// signed decimal integer.
private static final String Exp = "[eE][+-]?" + Digits;
private static final String fpRegex = ("[\x00-\x20]*" + // Optional leading "whitespace"
"[+-]?(" + // Optional sign character
"NaN|" + // "NaN" string
"Infinity|" + // "Infinity" string
// A decimal floating-point string representing a finite positive
// number without a leading sign has at most five basic pieces:
// Digits . Digits ExponentPart FloatTypeSuffix
//
// Since this method allows integer-only strings as input
// in addition to strings of floating-point literals, the
// two sub-patterns below are simplifications of the grammar
// productions from the Java Language Specification, 2nd
// edition, section 3.10.2.
// Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
"(((" + Digits + "(\.)?(" + Digits + "?)(" + Exp + ")?)|" +
// . Digits ExponentPart_opt FloatTypeSuffix_opt
"(\.(" + Digits + ")(" + Exp + ")?)|" +
// Hexadecimal strings
"((" +
// 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
"(0[xX]" + HexDigits + "(\.)?)|" +
// 0[xX] HexDigits_opt . HexDigits BinaryExponent
// FloatTypeSuffix_opt
"(0[xX]" + HexDigits + "?(\.)" + HexDigits + ")" +
")[pP][+-]?" + Digits + "))" + "[fFdD]?))" + "[\x00-\x20]*");// Optional
// trailing
// "whitespace"
}
- 在Java中,使用泛型是一件好事。这样,我们就可以为编译器和虚拟机提供有关要使用的类型的提示。在这种情况下,它是double值,并且通过声明结果List包含double值,则可以使用这些值而无需强制转换/类型转换:
if (!readRange.isEmpty()) {
double last = readRange.get(readRange.size() - 1);
}
- 使用Java集合时最好返回接口,因为有许多特定列表的实现(LinkedList,SynchronizedLists等)。因此,如果以后需要另一种类型的List,则可以轻松地更改方法内部的具体实现,而无需更改任何其他代码。
- 我们可能想知道while控制语句为什么起作用,但是如我们所见,next = input.next()。trim()周围有方括号。这样,变量分配就在条件测试之前进行。修剪饰边也可以避免白间距问题
- 我不在这里使用nextDouble(),因为每当用户输入不是double的内容时,我们都会得到一个异常。通过使用String,我可以解析用户提供的任何输入,还可以根据结束信号进行测试。
- 可以肯定的是,用户确实输入了double,因此我使用了Double.valueOf()方法的JavaDoc中的正则表达式。如果此表达式匹配,则将转换该值,否则将打印错误消息。
- 我们使用计数器是出于我在代码中看不到的原因。如果我们想知道已经成功输入了多少个值,只需调用readRange.size()。
- 如果要处理数组,则构造函数的第二部分将说明如何进行转换。
- 我希望我们不要被我混淆为double和Double,但是由于Java 1.5的自动装箱功能,这没问题。而且由于Scanner.next()永远不会返回null(afaik),所以这根本不是问题。
- 如果要限制数组的大小,请使用
好的,我希望我们对我的解决方案和解释有所帮助,使用result.size()作为指标,使用关键字break留下while控制语句。
加的特Greetz

