#java #arrays #string #exception
#java #массивы #строка #исключение
Вопрос:
у меня возникли проблемы с созданием программы, которая преобразует строку чисел в массив.
я знаю, что здесь есть аналогичный вопрос, но все, с чем мне нужно работать, — это набор чисел, таких как [10 15 16 0 57 438 57 18]
вот что у меня есть до сих пор:
import java.util.Scanner;
public class Histogram {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
String numbers;
numbers = keyboard.next();
System.out.println(numbers);
int [] n1 = new int [numbers.length()];
for(int n = 0; n < numbers.length(); n ) {
n1[n] = Integer.parseInt(numbers.split(" ")[n]);
}
}
}
этот код выдает исключение:
10 15 20 25 30
10
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at Histogram.main(Histogram.java:18)
что я делаю не так? я хочу избежать использования запятых для разделения элементов. кто-нибудь может объяснить, почему генерируется исключение и как это исправить? я хочу понять больше всего на свете.
Ответ №1:
Вы должны разделить строку один раз и сохранить массив где-нибудь.
Здесь вы выполняете итерацию до количества символов в строке, а не до количества чисел, разделенных пробелами.
int [] n1 = new int [numbers.length()];
for(int n = 0; n < numbers.length(); n ) {
n1[n] = Integer.parseInt(numbers.split(" ")[n]);
}
Изменить на:
String[] parts = numbers.split(" ");
int[] n1 = new int[parts.length];
for(int n = 0; n < parts.length; n ) {
n1[n] = Integer.parseInt(parts[n]);
}
Посмотрите, как это работает онлайн: ideone
Комментарии:
1. Я немного смущен. что происходит? можете ли вы уточнить?
2. @chris: Сколько символов в
10 15 16 0 57 438 57 18
нем? Подсказка: больше 8!3. @chris, вы ищете длину того, что
split()
возвращается (массив фрагментов строки), а не длину всей строки.
Ответ №2:
Вот что происходит:
numbers = keyboard.next();
System.out.println(numbers);
//This line is creating an array with the length in characters of the String which in this case is 14
int [] n1 = new int [numbers.length()];
//Then When you split the number there is really only 5 elements, yet numbers.length() is 14, therefore when asking for the array on position 6 it causes the exception.
for(int n = 0; n < numbers.length(); n ) {
n1[n] = Integer.parseInt(numbers.split(" ")[n]);
Дополнительно вы должны просто выполнить эту операцию numbers.split(» «) один раз, а затем просто получить к ней доступ следующим образом:
String [] stringParts = numbers.split(" "):
stringParts[n]
Итак, в основном ваш for действительно выглядит примерно так:
for(int n = 0; n < 14; n )
{
}
а затем numbers.split(» «) возвращает только 5 элементов, поскольку всего 5 чисел, поэтому, когда вы запрашиваете позицию 6, выдается исключение, поскольку массив имеет только размер 5.
Ответ №3:
Я создал этот класс для своего личного использования, но я думаю, что он может помочь вам с вашей проблемой.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class ArrayUtils {
private static final Logger log = LoggerFactory.getLogger(ArrayUtils.class);
private static final Map<Class, Class> primitiveMapping = new HashMap<Class, Class>();
private static final Map<Class, Method> primitiveParseMethodLookup = new HashMap<Class, Method>();
private static final Map<Class, Method> primitiveArrayGetMethodLookup = new HashMap<Class, Method>();
private static final Map<Class, Method> valueOfMethodLookup = new HashMap<Class, Method>();
static {
// Initialize primitive mappings
primitiveMapping.put(boolean.class, Boolean.class);
primitiveMapping.put(byte.class, Byte.class);
primitiveMapping.put(short.class, Short.class);
primitiveMapping.put(int.class, Integer.class);
primitiveMapping.put(float.class, Float.class);
primitiveMapping.put(long.class, Long.class);
primitiveMapping.put(double.class, Double.class);
// Initialize parse, valueOf and get method lookup
// We do that in advance because the lookup of the method takes the longest time
// Compared to the normal method call it's 20x higher
// So we use just the reflective method call which takes double the time of a normal method call
try {
primitiveParseMethodLookup.put(boolean.class, Boolean.class.getMethod("parseBoolean", new Class[]{String.class}));
primitiveParseMethodLookup.put(byte.class, Byte.class.getMethod("parseByte", new Class[]{String.class}));
primitiveParseMethodLookup.put(short.class, Short.class.getMethod("parseShort", new Class[]{String.class}));
primitiveParseMethodLookup.put(int.class, Integer.class.getMethod("parseInt", String.class));
primitiveParseMethodLookup.put(float.class, Float.class.getMethod("parseFloat", String.class));
primitiveParseMethodLookup.put(long.class, Long.class.getMethod("parseLong", String.class));
primitiveParseMethodLookup.put(double.class, Double.class.getMethod("parseDouble", String.class));
valueOfMethodLookup.put(Boolean.class, Boolean.class.getMethod("valueOf", new Class[]{String.class}));
valueOfMethodLookup.put(Byte.class, Byte.class.getMethod("valueOf", new Class[]{String.class}));
valueOfMethodLookup.put(Short.class, Short.class.getMethod("valueOf", new Class[]{String.class}));
valueOfMethodLookup.put(Integer.class, Integer.class.getMethod("valueOf", String.class));
valueOfMethodLookup.put(Float.class, Float.class.getMethod("valueOf", String.class));
valueOfMethodLookup.put(Long.class, Long.class.getMethod("valueOf", String.class));
valueOfMethodLookup.put(Double.class, Double.class.getMethod("valueOf", String.class));
primitiveArrayGetMethodLookup.put(boolean.class, Array.class.getMethod("getBoolean", new Class[]{Object.class, int.class}));
primitiveArrayGetMethodLookup.put(byte.class, Array.class.getMethod("getByte", new Class[]{Object.class, int.class}));
primitiveArrayGetMethodLookup.put(short.class, Array.class.getMethod("getShort", new Class[]{Object.class, int.class}));
primitiveArrayGetMethodLookup.put(int.class, Array.class.getMethod("getInt", Object.class, int.class));
primitiveArrayGetMethodLookup.put(float.class, Array.class.getMethod("getFloat", Object.class, int.class));
primitiveArrayGetMethodLookup.put(long.class, Array.class.getMethod("getLong", Object.class, int.class));
primitiveArrayGetMethodLookup.put(double.class, Array.class.getMethod("getDouble", Object.class, int.class));
} catch (NoSuchMethodException e) {
//******************************
// This can never happen
//******************************
}
}
public static boolean isArrayOfPrimitives(Object object) {
if (object.getClass().isArray()) {
return object.getClass().getComponentType().isPrimitive();
}
return false;
}
public static boolean isArrayOf(Object object, Class clazz) {
if (object.getClass().isArray()) {
return clazz.isAssignableFrom(object.getClass().getComponentType());
}
return false;
}
/**
* Convert any array of primitives(excluding char), strings or numbers into any other array
* of strings or numbers.
*
* @param array Array of primitives(excluding char), strings or numbers
* @param convertedArrayComponentType Converted array component type (String or Number)
* @param <T> To allow implicit casting
* @return Array of convertedArrayComponentType
*/
public static <T> T[] convertArray(Object array, Class<T> convertedArrayComponentType) {
// Collect data regarding arguments
final boolean arrayOfPrimitives = isArrayOfPrimitives(array);
final boolean arrayOfCharPrimitives = isArrayOf(array, char.class);
final boolean arrayOfCharacters = isArrayOf(array, Character.class);
final boolean arrayOfStrings = isArrayOf(array, String.class);
final boolean arrayOfNumbers = isArrayOf(array, Number.class);
// Check if array is an array of strings, primitives or wrapped primitives
if (!arrayOfPrimitives amp;amp; !arrayOfNumbers amp;amp; !arrayOfStrings || arrayOfCharPrimitives || arrayOfCharacters) {
throw new IllegalArgumentException(array " must be an array of of strings, primitives or boxed primitives (byte, boolean, short, int, float, long, double)");
}
// Check if it's assignable from Number of String
if (!Number.class.isAssignableFrom(convertedArrayComponentType) amp;amp; !String.class.isAssignableFrom(convertedArrayComponentType)) {
throw new IllegalArgumentException(convertedArrayComponentType " must be a Number or a String");
}
try {
return (T[]) convertArrayInternal(array, convertedArrayComponentType);
} catch (InvocationTargetException e) {
// This can happen due to errors in conversion
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
// This should never happen
log.error("Something went really wrong in ArrayUtils.convertArray method.", e);
}
// To satisfy the compiler
return null;
}
/**
* Convert any array of primitives(excluding char), strings or numbers into an array
* of primitives(excluding char).
*
* @param array Array of primitives(excluding char), strings or numbers
* @param convertedArrayComponentType Converted array component type primitive(excluding char)
* @return Array of convertedArrayComponentType
*/
public static Object convertToPrimitiveArray(Object array, Class convertedArrayComponentType) {
// Collect data regarding arguments
final boolean arrayOfPrimitives = isArrayOfPrimitives(array);
final boolean arrayOfCharPrimitives = isArrayOf(array, char.class);
final boolean arrayOfCharacters = isArrayOf(array, Character.class);
final boolean arrayOfStrings = isArrayOf(array, String.class);
final boolean arrayOfNumbers = isArrayOf(array, Number.class);
// Check if array is an array of strings, primitives or wrapped primitives
if (!arrayOfPrimitives amp;amp; !arrayOfNumbers amp;amp; !arrayOfStrings || arrayOfCharPrimitives || arrayOfCharacters) {
throw new IllegalArgumentException(array " must be an array of of strings, primitives or boxed primitives (byte, boolean, short, int, float, long, double)");
}
// Check if it's assignable from Number of String
if (!convertedArrayComponentType.isPrimitive() || convertedArrayComponentType.isAssignableFrom(char.class)) {
throw new IllegalArgumentException(convertedArrayComponentType " must be a primitive(excluding char)");
}
try {
return convertArrayInternal(array, convertedArrayComponentType);
} catch (InvocationTargetException e) {
// This can happen due to errors in conversion
throw (RuntimeException) e.getTargetException();
} catch (Exception e) {
// This should never happen
log.error("Something went really wrong in ArrayUtils.convertArray method.", e);
}
// To satisfy the compiler
return null;
}
private static Object convertArrayInternal(Object array, Class convertedArrayComponentType) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
// Lookup the primitive parse method or the boxed primitive valueOf method
final Method convertMethod;
if (convertedArrayComponentType.isPrimitive()) {
convertMethod = primitiveParseMethodLookup.get(convertedArrayComponentType);
} else {
convertMethod = valueOfMethodLookup.get(convertedArrayComponentType);
}
// If the array is an array of primitives lookup the get method
final Method primitiveArrayGetMethod = primitiveArrayGetMethodLookup.get(array.getClass().getComponentType());
// Get length and create new array
final int arrayLength = Array.getLength(array);
final Object castedArray = Array.newInstance(convertedArrayComponentType, arrayLength);
for (int i = 0; i < arrayLength; i ) {
final Object value;
if (primitiveArrayGetMethod != null) {
value = primitiveArrayGetMethod.invoke(null, array, i);
} else {
value = Array.get(array, i);
}
final String stringValue = String.valueOf(value);
final Object castedValue = convertMethod.invoke(null, stringValue);
Array.set(castedArray, i, castedValue);
}
return castedArray;
}
}
Его можно использовать следующим образом:
String[] strings = new String[]{"1", "2", "3"};
Integer[] integers = ArrayUtils.convertArray(strings, Integer.class);
int[] ints = (int[]) ArrayUtils.convertToPrimitiveArray(strings, int.class);