leer - scanner java
ArrayList en Java y entrada (4)
Estoy acostumbrado a Python, así que esto es un poco confuso para mí. Estoy tratando de introducir datos, línea por línea, hasta que un usuario ingrese un cierto número. Los números se almacenarán en una matriz para aplicarles algunas matemáticas estadísticas. Actualmente, tengo una clase principal, las clases de estadísticas y una clase de "lectura".
Dos preguntas:
Parece que no puedo hacer funcionar el ciclo de entrada, ¿cuál es la mejor práctica para hacerlo?
¿Cuál será el tipo de objeto para el método de lectura? ¿Un doble [] o un ArrayList?
¿Cómo declaro que method-type es un arraylist?
¿Cómo evito que la matriz tenga más de 1000 valores almacenados en ella?
Déjame mostrar lo que tengo hasta ahora:
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;
}
Cualquier ayuda sería apreciada, perdón por mi novedad ...
Creo que comenzaste no está mal, pero esta es mi sugerencia. Resaltaré las diferencias importantes y los puntos debajo del código:
consola del paquete;
import java.util. ; import java.util.regex. ;
clase pública 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"
}
En Java, es bueno usar genéricos. De esta manera, le da al compilador y a la máquina virtual una pista sobre los tipos que está a punto de usar. En este caso es doble y al declarar que la Lista resultante contiene valores dobles, puede usar los valores sin conversión de conversión / conversión:
if (!readRange.isEmpty()) { double last = readRange.get(readRange.size() - 1); }
Es mejor devolver interfaces cuando se trabaja con colecciones Java, ya que hay muchas implementaciones de listas específicas (LinkedList, SynchronizedLists, ...). Entonces, si necesita otro tipo de lista más adelante, puede cambiar fácilmente la implementación concreta dentro del método y no necesita cambiar ningún código adicional.
Puede que se pregunte por qué el enunciado de control while funciona, pero como ve, hay corchetes alrededor de next = input.next (). Trim () . De esta forma, la asignación de variables tiene lugar justo antes de la prueba condicional. También se necesita un ajuste para evitar problemas de espacio en blanco
No estoy usando nextDouble () aquí porque cada vez que un usuario ingresa algo que no es doble, bueno, obtendrá una excepción. Al utilizar String, puedo analizar cualquier entrada que el usuario proporcione, pero también probarla con la señal final.
Para estar seguro, un usuario realmente incluyó un doble, utilicé una expresión regular de JavaDoc del método Double.valueOf () . Si esta expresión coincide, el valor se convierte, de lo contrario se imprimirá un mensaje de error.
Usaste un contador por razones que no veo en tu código. Si desea saber cuántos valores se han ingresado con éxito, simplemente llame a readRange.size () .
Si desea trabajar con una matriz, la segunda parte del constructor muestra cómo convertirla.
Espero que no te confundas al mezclar doble y doble, pero gracias a la característica de Java 1.5 Auto-Boxing esto no es problema. Y como Scanner.next () nunca devolverá null (afaik), esto no debería ser un problema en absoluto.
Si quiere limitar el tamaño de la matriz, use
De acuerdo, espero que encuentres útil mi solución y mis explicaciones, usa result.size () como indicador y la palabra clave break para dejar la declaración de control while.
Greetz, GHad
Lo que necesitas en tu condición de bucle es:
while ( input.get( input.size()-1 ) != end_signal );
Lo que estás haciendo es decrementar la variable contraria.
También deberías declarar ArrayList
así:
ArrayList<Double> list = new ArrayList<Double>();
Esto hace que la lista sea específica para el tipo y permite la condición como dada. De lo contrario, hay un casting extra.
Respuestas
> 1. Parece que no puedo hacer funcionar el ciclo de entrada, ¿cuál es la mejor práctica para hacerlo?
Preferiría tener un simple while while en lugar de do {} mientras ... y colocar la condición en el momento ... En mi ejemplo, decía:
mientras que el número de lectura no es señal final y el recuento es menor que el límite: do.
> 2. ¿Cuál será el tipo de objeto para el método de lectura? ¿Un doble [] o un ArrayList?
Una ArrayList, sin embargo, le recomiendo encarecidamente que use la interfaz List (java.util.List) en su lugar. Es una buena práctica de OO programar en la interfaz en lugar de la implementación.
> 2.1¿Cómo declaro que method-type es un arraylist?
Vea el código a continuación.
> 2.2. ¿Cómo evito que la matriz tenga más de 1000 valores almacenados en ella?
Al agregar esta restricción en la condición de tiempo.
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;
}
}
Observaciones finales:
Se prefiere tener "métodos de instancia" que los métodos de clase. De esta forma, si fuera necesario, el "readRange" podría ser manejado por una subclase sin tener que cambiar la firma, por lo tanto, en la muestra eliminé la palabra clave "static" y creé una instancia de la clase "InputTest".
En el estilo de código java, los nombres de las variables deben ir en el caso cammel como en "endSignal" en lugar de "end_signal"
**
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;
}
**