ArrayList в Java и ввод
Вопрос
Я привык к Python, поэтому меня это немного сбивает с толку.Я пытаюсь вводить данные построчно, пока пользователь не введет определенное число.Числа будут сохранены в массиве, чтобы применить к ним некоторые статистические математические вычисления.В настоящее время у меня есть основной класс, классы статистики и класс «чтения».
Два вопроса:
Кажется, я не могу заставить цикл ввода работать, как лучше всего это сделать.
Каким будет тип объекта для метода чтения?Двойной [] или ArrayList?
Как объявить тип метода как список массивов?
Как предотвратить сохранение в массиве более 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;
}
Любая помощь будет оценена по достоинству, простите за новичок...
Решение
Ответы:
>1.Кажется, я не могу заставить цикл ввода работать, как лучше всего это сделать.
Я бы предпочел использовать простой цикл while вместо do{} while...и поместите условие в while...В моем примере было написано:
пока число чтения не является конечным сигналом и счетчик ниже предела:делать.
>2.Каким будет тип объекта для метода чтения?Двойной [] или ArrayList?
ArrayList, однако я настоятельно рекомендую вместо этого использовать интерфейс List ( java.util.List ).Хорошей объектно-ориентированной практикой является программирование для интерфейса, а не для реализации.
>2.1Как объявить тип метода как список массивов?
См. код ниже.
>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».
Другие советы
Что вам нужно в вашем условии цикла:
while ( input.get( input.size()-1 ) != end_signal );
Что вы делаете, так это уменьшаете переменную счетчика.
Также вам следует объявить ArrayList
вот так:
ArrayList<Double> list = new ArrayList<Double>();
Это делает список специфичным для типа и допускает заданное условие.В противном случае будет дополнительный кастинг.
Я думаю, вы начали неплохо, но вот мое предложение.Я выделю важные различия и моменты под кодом:
консоль пакета;
импортируйте 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 полезно использовать дженерики.Таким образом вы дадите компилятору и виртуальной машине подсказку о типах, которые вы собираетесь использовать.В этом случае его двойной и объявляя полученный список содержать двойные значения, вы можете использовать значения без преобразования литья/типа:
if (!readRange.isEmpty()) { double last = readRange.get(readRange.size() - 1); }
При работе с коллекциями Java лучше возвращать интерфейсы, так как существует множество реализаций конкретных списков (LinkedList, SynchronizedLists,...).Поэтому, если позже вам понадобится другой тип списка, вы можете легко изменить конкретную реализацию внутри метода, и вам не нужно будет менять какой-либо дополнительный код.
Вы можете задаться вопросом, почему оператор управления while работает, но, как видите, вокруг него есть скобки. следующий = input.next().trim().Таким образом, присвоение переменной происходит непосредственно перед условным тестированием.Также обрезка требует воспроизведения, чтобы избежать проблем с пробелами.
я не использую следующийДабл() здесь, потому что всякий раз, когда пользователь вводит что-то, кроме двойного значения, вы получаете исключение.Используя String, я могу анализировать любые входные данные, вводимые пользователем, а также проверять конечный сигнал.
Чтобы быть уверенным, что пользователь действительно ввел двойное значение, я использовал регулярное выражение из JavaDoc Двойной.valueOf() метод.Если это выражение соответствует, значение преобразуется, в противном случае будет напечатано сообщение об ошибке.
Вы использовали счетчик по причинам, которые я не вижу в вашем коде.Если вы хотите узнать, сколько значений было введено успешно, просто позвоните readRange.size().
Если вы хотите работать с массивом, вторая часть конструктора показывает, как его преобразовать.
Надеюсь, вас не смутило то, что я смешиваю double и Double, но благодаря функции Auto-Boxing в Java 1.5 это не проблема.И в качестве Сканер.следующий() никогда не вернет ноль (афаик), это вообще не должно быть проблемой.
Если вы хотите ограничить размер массива, используйте
Хорошо, я надеюсь, что вы найдете мое решение и объяснения полезными, используйте результат.размер() как индикатор и ключевое слово перерыв оставить оператор управления while.
Гретц, Гад
**
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;
}
**
public static ArrayList<Double> readRange(double end_signal) {
ArrayList<Double> input = new ArrayList<Double>();
Scanner kbd = new Scanner( System.in );
int count = 0;
do{
input.add(kbd.nextDouble());
++count;
} while(input(--count) != end_signal);
return input;
}