【问题标题】:Convert a string of numbers into an array将一串数字转换为数组
【发布时间】:2023-03-18 15:26:02
【问题描述】:

我在创建将一串数字转换为数组的程序时遇到问题。

我知道这里有一个类似的问题,但我只需要处理一组数字,例如 [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)

我做错了什么?我想避免使用逗号分隔元素。谁能解释为什么抛出异常以及如何解决它?我比什么都想明白。

【问题讨论】:

    标签: java arrays string exception


    【解决方案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

    【讨论】:

    • 我有点困惑。发生了什么?能详细点吗?
    • @chris:10 15 16 0 57 438 57 18 中有多少个字符?提示:超过 8 个!
    • @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 && !arrayOfNumbers && !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) && !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 && !arrayOfNumbers && !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);
      

      【讨论】:

        猜你喜欢
        • 2019-12-10
        • 2013-03-18
        • 2015-04-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-04
        • 2017-11-27
        相关资源
        最近更新 更多