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