【问题标题】:How to realize a Generic method of conversion from List<T> to T[]?如何实现从 List<T> 到 T[] 的通用转换方法?
【发布时间】:2014-01-04 13:19:48
【问题描述】:

我想实现一个基于泛型的 java 方法将 List&lt;T&gt; 转换为 T[]

比如我有一个List&lt;T&gt;,比如List&lt;Double&gt;

List<Double> lst = Arrays.asList( new Double[]{1.11, 2.22, 3.33} );

我有以下方法:

public static <T> T[] listToArray(List<T> inputList)
{
    @SuppressWarnings("unchecked")
    Class<T> type = (Class<T>)NumberTypeOfString(inputList.get(0).toString());
    @SuppressWarnings("unchecked")
    T[] resultArray = (T[]) Array.newInstance(type, inputList.size());

    for(int i=0; i < inputList.size(); i++)
    {
        resultArray[i] = (T)inputList.get(i);
    }
    return resultArray;
}

当我这样调用这个方法时:

Double[] resultArray = listToArray(lst);

我得到一个我真的无法理解的异常:

java.lang.ArrayStoreException: java.lang.String

为什么会这样?

PS:上面的方法“NumberTypeOfString”是输入一个像“1.11”这样的String,得到一个像Double.class这样的类型,其他数字类型也是如此。

编辑:

我将删除第二个问题(“有什么方法可以正确实现该方法吗?”),以便更多地关注这段代码。

解决方案和深度问题:

Just use List<Double> and nothing goes wrong at all.

但是,事实上,我有一个方法可以生成返回 ArrayList 的 AP 或 GP:

ArrayList<Double> arrayOfResult = createArrayOfProgression("ratio; 1; 2; 12;12");

其中,“ratio;1;2;12;12”表示选择;第一的;步;最后的;总数。

arrayOfResult 的内容是:

[1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 2048.0]

调用this的结果是一个ArrayList,但是后来这个arrayOfResult被输入到listToArray中时导致了上面的异常。 代码如下:

    public enum caculator{
    diff, ratio;
}

public static <T> ArrayList<T> createArrayOfProgression(String firstStepLastTotal)
{
    String[] arrayOfParameter = firstStepLastTotal.replace(" ", "").split(";");
    String choice = arrayOfParameter[0];

    double first = Double.valueOf(arrayOfParameter[1]);
    double step = Double.valueOf(arrayOfParameter[2]);
    String strlast = arrayOfParameter[3];
    String strtotal = "";
    if(arrayOfParameter.length == 5)
    {
        strtotal = arrayOfParameter[4];
    }
    else
    {
        strtotal = "";
    }

    Class<?> classOfNumber = NumberTypeOfString(arrayOfParameter[2]);

    String strResult = "";
    /**
     * 1. Generate AP or OP by the total number of progression
     */
    if( !strtotal.equals("") && strlast.equals("") )
    {
        for(int i = 0; i < Integer.valueOf(strtotal); i++)
        {
            switch(caculator.valueOf(choice))
            {
            case diff:
                strResult += ( first + step * (i) )+ "\n";
                break;
            case ratio:
                strResult += ( first * java.lang.Math.pow(step, (i))) + "\n";
                break;
            }
        }
    }
    /**
     * 2. Generate AP or OP by the last item
     */
    else if( strtotal.equals("") && !strlast.equals("") )
    {
        int locationFirst = 0;
        int locationLast = (int)(Double.valueOf(strlast) -first) / (int)step + 1;
        for(int i = 0; i < locationLast - locationFirst; i++)
        {
            switch(caculator.valueOf(choice))
            {
            case diff:
                strResult += ( first + step * (i) )+ "\n";
                break;
            case ratio:
                strResult += ( first * java.lang.Math.pow(step, (i))) + "\n";
                break;
            }
        }
    }
    /**
     * 3. Generate AP or OP by the last item or by the total number of progression
     */
    else if( !strtotal.equals("") && !strlast.equals("") )
    {
        int locationFirst = 0;
        int locationLast = (int)(Double.valueOf(strlast) -first) / (int)step + 1;
        int locationTotal = Integer.valueOf(strtotal);
        for(int i = 0; i < ((locationLast - locationFirst)>locationTotal? (locationLast - locationFirst):locationTotal); i++)
        {
            switch(caculator.valueOf(choice))
            {
            case diff:
                strResult += ( first + step * (i) )+ "\n";
                break;
            case ratio:
                strResult += ( first * java.lang.Math.pow(step, (i))) + "\n";
                break;
            }
        }
    }
    else
    {
        System.out.println("Wrong!!");
    }
    System.out.println("classOfNumber="+classOfNumber);
    String[] arrayOfResult = strResult.split("\n");

    ArrayList<T> resultList = new ArrayList<T>();
    for(int i = 0; i < arrayOfResult.length; i++)
    {
        @SuppressWarnings("unchecked")
        T elem = (T) arrayOfResult[i];
        resultList.add( elem );
    }

    return resultList;
}

但是, 我用下面的 ArrayList 测试,没有问题:

ArrayList<Double> alst = new ArrayList<Double>();
    alst.add(1.11);
    alst.add(2.22);
    alst.add(3.33);
Double[] DresultArray = listToArray(alst);

当我使用这个时:

ArrayList<Double> arrayOfResult = createArrayOfProgression("diff; 1.11; 1.11; ;3");
//which has the same content: [1.11, 2.22, 3.33], 
Double[] DresultArray = listToArray(arrayOfResult);

又跳出一个异常:

java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to [Ljava.lang.Double;

我还是不知道为什么……

【问题讨论】:

标签: java arrays generics arraylist


【解决方案1】:

Arrays.asList() returns an ArrayList which extends AbstractList and NOT ArrayList!
因此你的例外java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to [Ljava.lang.Double

因此,如果您使用 java.util.ArrayList 作为基本类型而不是 java.util.List,请将您的代码更改为以下代码。

public class G {

public static <T> T[] listToArray(ArrayList<T> inputList)
{
    @SuppressWarnings("unchecked")
    Class<T> type = (Class<T>)inputList.get(0).getClass();
    @SuppressWarnings("unchecked")
    T[] resultArray = (T[]) Array.newInstance(type, inputList.size());

    for(int i=0; i < inputList.size(); i++)
    {
        resultArray[i] = (T)inputList.get(i);
    }
    return resultArray;
}

public static void main( String[] args ) {
    ArrayList<Double> lst = new ArrayList( Arrays.asList( new Double[]{1.11, 2.22, 3.33} ) );
    Double[] d = listToArray( lst );
    System.out.println(d[0]);
}

}

【讨论】:

  • 我尝试运行这个: ArrayList arrayOfResult = createArrayOfProgression("diff; 1.11; 1.11; ;3"); ArrayList alst2 = new ArrayList(arrayOfResult);但是还是遇到一个异常:[Ljava.lang.String;不能转换为[Ljava.lang.Double;,还是谢谢你的回答!
  • 错误代码:String[] arrayOfResult = strResult.split("\n"); 然后你有这个`T elem = (T) arrayOfResult[i];`。显然 String 不能转换为 Double。将 Class 作为方法参数传递,然后使用 Arrays.newInstance()。它应该可以正常工作。
  • 谢谢!!我发现这种输入类型的方式是一个很好的解决方案,使用 T[] arrayOfResult = (T[]) getNumberArrayFromStringArray(strResult.split("\n"));哪个方法getNumberArrayFromStringArray()把数字格式的Stirng数组变成了数字类型的数组,我终于看不出异常了!!
  • 您仍然需要在方法getNumbere FromArray()中输入确切的数字类,数组中的数字可以是Double或Long
  • 你完全正确,我使用了很多正则表达式和 if-else 来查找数组 elem 的数字类型并返回 Class> 因为我不知道官方包是否提供类似的功能.
【解决方案2】:

改变这个:

Class<T> type = (Class<T>)NumberTypeOfString(inputList.get(0).toString());

对此:

Class<T> type = (Class<T>)(inputList.get(0).getClass());

来自Array.newInstance doc:

componentType - 表示组件类型的 Class 对象 新数组

所以新数组的类型需要是List中元素的类型。

【讨论】:

  • 我运行这个新的但得到另一个异常:java.lang.ClassCastException: [Ljava.lang.String;不能转换为 [Ljava.lang.Double;
  • 对不起我的错,我输入了一个 ArrayList 而不是 List 然后发生了!我将把问题改为为什么 ArrayList 会导致这种情况。谢谢你!!
  • 衷心感谢!我再次为另一种生成算术级数或几何级数的相关方法编辑我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
  • 1970-01-01
  • 2013-10-06
相关资源
最近更新 更多