Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Java 8中的supplier ClassCastEx b/c类型的erasure用通用列表填充数组_Java_Arrays_Generics_Lambda - Fatal编程技术网

使用Java 8中的supplier ClassCastEx b/c类型的erasure用通用列表填充数组

使用Java 8中的supplier ClassCastEx b/c类型的erasure用通用列表填充数组,java,arrays,generics,lambda,Java,Arrays,Generics,Lambda,我想使用Supplier和Stream.generate将通用列表作为元素填充数组 看起来像这样: Supplier<List<Object>> supplier = () -> new ArrayList<Object>(); List<Object>[] test = (List<Object>[]) Stream.generate(supplier).limit(m).toArray(); Supp

我想使用Supplier和Stream.generate将通用列表作为元素填充数组

看起来像这样:

    Supplier<List<Object>> supplier = () -> new ArrayList<Object>();
    List<Object>[] test = (List<Object>[]) Stream.generate(supplier).limit(m).toArray();
    Supplier<List<Integer>> supplier = () -> { 
        ArrayList<Integer> a = new ArrayList<Integer>();
        a.add(5);
        a.add(8);
        return a;
    };

    Object[] objArr = Stream.generate(supplier).limit(3).toArray();
    for (Object o : objArr) {
        ArrayList<Integer> arrList = (ArrayList<Integer>) o; // This is not safe to do, compiler can't know this is safe.
        System.out.println(arrList.get(0)); 
    }
现在,如何使用Java8提供的技术用泛型类型填充数组?或者这根本不可能(现在),我必须用“经典”的方式来做

问候,, 克拉斯M

编辑

根据@Water的请求,我使用stream.collect(使用Cast测试数组)和传统的迭代方法填充数组/列表,进行了一些性能测试

首先,使用列表进行性能测试:

private static int m = 100000;

/**
 * Tests which way is faster for LISTS.
 * Results:
 * 1k Elements: about the same time (~5ms)
 * 10k Elements: about the same time (~8ms)
 * 100k Elements: new way about 1.5x as fast (~18ms vs ~27ms)
 * 1M Elements: new way about 2x as fast (~30ms vs ~60ms)
 * NOW THIS IS INTERESTING:
 * 10M Elements: new way about .1x as fast (~5000ms vs ~500ms)
 * (100M OutOfMemory after ~40Sec)
 * @param args
 */

public static void main(String[] args) {

    Supplier<String> supplier = () -> new String();
    long startTime,endTime;

    //The "new" way
    startTime = System.currentTimeMillis();
    List<String> test1 =  Stream.generate(supplier).limit(m ).collect(Collectors.toList());
    endTime = System.currentTimeMillis();
    System.out.println(endTime - startTime);


    //The "old" way
    startTime = System.currentTimeMillis();
    List<String> test2 = new ArrayList();
    Iterator<String> i = Stream.generate(supplier).limit(m).iterator();
    while (i.hasNext()) {
        test2.add(i.next());
    }
    endTime = System.currentTimeMillis();
    System.out.println(endTime - startTime);


}
private static int m=100000;
/**
*测试列表的哪种方式更快。
*结果:
*1k元素:大约在同一时间(~5ms)
*10k元件:大约在同一时间(~8ms)
*10万个元素:新方法速度约为1.5倍(~18毫秒vs~27毫秒)
*1M元素:新方法快2倍(约30毫秒vs约60毫秒)
*这很有趣:
*10M元素:新方法,速度约为0.1x(~5000ms vs~500ms)
*(约40秒后100米内存外)
*@param args
*/
公共静态void main(字符串[]args){
供应商=()->新字符串();
漫长的开始时间,漫长的结束时间;
//“新”方式
startTime=System.currentTimeMillis();
List test1=Stream.generate(supplier.limit(m).collect(Collectors.toList());
endTime=System.currentTimeMillis();
System.out.println(endTime-startTime);
//“旧”方式
startTime=System.currentTimeMillis();
List test2=new ArrayList();
迭代器i=Stream.generate(supplier).limit(m).Iterator();
while(i.hasNext()){
test2.add(i.next());
}
endTime=System.currentTimeMillis();
System.out.println(endTime-startTime);
}
第二,使用阵列进行性能测试:

    private static int m = 100000000;

    /**
     * Tests which way is faster for ARRAYS.
     * Results:
     * 1k Elements: old way much faster (~1ms vs ~6ms)
     * 10k Elements: old way much faster (~2ms vs ~7ms)
     * 100k Elements: old way about 2x as fast (~7ms vs ~14ms)
     * 1M Elements: old way a bit faster (~50ms vs ~60ms)
     * 10M Elements: old way a bit faster (~5s vs ~6s)
     * 100M Elements: Aborted after about 5 Minutes of 100% CPU Utilisation on an i7-2600k
     * @param args
     */

    public static void main(String[] args) {

        Supplier<String> supplier = () -> new String();
        long startTime,endTime;

        //The "new" way
        startTime = System.currentTimeMillis();
        String[] test1 =  (String[]) Stream.generate(supplier).limit(m ).collect(Collectors.toList()).toArray(new String[m]);
        endTime = System.currentTimeMillis();
        System.out.println(endTime - startTime);


        //The "old" way
        startTime = System.currentTimeMillis();
        String[] test2 = new String[m];
        Iterator<String> it = Stream.generate(supplier).iterator();
        for(int i = 0; i < m; i++){
            test2[i] = it.next();
        }
        endTime = System.currentTimeMillis();
        System.out.println(endTime - startTime);


    }

}
private static int m=100000000;
/**
*测试阵列的哪种方式更快。
*结果:
*1k元素:旧方法快得多(~1ms vs~6ms)
*10k元素:旧方法快得多(~2ms vs~7ms)
*10万个元素:旧方法快2倍(约7毫秒vs约14毫秒)
*1M元素:旧方法快一点(~50ms vs~60ms)
*10M元素:旧方法快一点(~5s vs~6s)
*100M元素:在i7-2600k上约5分钟的100%CPU利用率后中止
*@param args
*/
公共静态void main(字符串[]args){
供应商=()->新字符串();
漫长的开始时间,漫长的结束时间;
//“新”方式
startTime=System.currentTimeMillis();
String[]test1=(String[])Stream.generate(supplier).limit(m).collect(Collectors.toList()).toArray(新字符串[m]);
endTime=System.currentTimeMillis();
System.out.println(endTime-startTime);
//“旧”方式
startTime=System.currentTimeMillis();
字符串[]test2=新字符串[m];
Iterator it=Stream.generate(supplier.Iterator();
for(int i=0;i
正如你所看到的,水的确是对的——石膏使它变慢了。 但对于列表,新方法更快;至少从100k到1M元件。
我仍然不知道为什么当涉及到10万个元素时速度会慢得多,我真的很想听到一些关于这方面的评论。

我想问题是您使用的toArray()没有返回Object[]的参数。看看

public <T> T[] toArray(T[] a)
public T[]toArray(T[]a)

流生成器仍然会生成您想要的对象,唯一的问题是调用toArray()会返回一个对象数组,并且您不能从对象数组向下转换为子对象数组(因为您有类似于:object[]{ArrayList,ArrayList})

下面是正在发生的事情的一个例子:

你认为你有这个:

    String[] hi = { "hi" };
    Object[] test = (Object[]) hi; // It's still a String[]
    String[] out = (String[]) test;
    System.out.println(out[0]); // Prints 'hi'
但实际上你有:

    String[] hi = { "hi" };
    Object[] test = new Object[1]; // This is not a String[]
    test[0] = hi[0];
    String[] out = (String[]) test; // Cannot downcast, throws an exception.
    System.out.println(out[0]);
你得到的是上面的直接块,这就是为什么你得到一个铸造错误

有几种方法可以解决这个问题。如果你想查看你的列表,你可以很容易地把它们做成一个数组

    Supplier<List<Integer>> supplier = () -> { 
        ArrayList<Integer> a = new ArrayList<Integer>();
        a.add(5);
        a.add(8);
        return a;
    };

    Iterator<List<Integer>> i = Stream.generate(supplier).limit(3).iterator();

    // This shows there are elements you can do stuff with.
    while (i.hasNext()) {
        List<Integer> list = i.next();
        // You could add them to your list here.
        System.out.println(list.size() + " elements, [0] = " + list.get(0));
    }
供应商=()->{
ArrayList a=新的ArrayList();
a、 增加(5);
a、 增加(8);
返回a;
};
迭代器i=Stream.generate(supplier).limit(3.Iterator();
//这表明有一些元素可以使用。
while(i.hasNext()){
List=i.next();
//您可以将它们添加到您的列表中。
System.out.println(list.size()+“元素,[0]=”+list.get(0));
}
如果设置了处理函数,则可以执行以下操作:

    Supplier<List<Object>> supplier = () -> new ArrayList<Object>();
    List<Object>[] test = (List<Object>[]) Stream.generate(supplier).limit(m).toArray();
    Supplier<List<Integer>> supplier = () -> { 
        ArrayList<Integer> a = new ArrayList<Integer>();
        a.add(5);
        a.add(8);
        return a;
    };

    Object[] objArr = Stream.generate(supplier).limit(3).toArray();
    for (Object o : objArr) {
        ArrayList<Integer> arrList = (ArrayList<Integer>) o; // This is not safe to do, compiler can't know this is safe.
        System.out.println(arrList.get(0)); 
    }
供应商=()->{
ArrayList a=新的ArrayList();
a、 增加(5);
a、 增加(8);
返回a;
};
Object[]objArr=Stream.generate(supplier).limit(3.toArray();
for(对象o:objArr){
ArrayList arrList=(ArrayList)o;//这样做不安全,编译器无法知道这样做是否安全。
System.out.println(arrList.get(0));
}

根据,如果您想将它转换为数组,您可以使用other toArray()方法,但是我还没有研究过这个函数,所以我不想讨论一些我不知道的东西。

这个函数不在javadocs中。有
A[]toArray(IntFunction generator)
,但我看不出你从哪里得到
public t[]toArray(t[]A)
。。。你确定你读过这个问题或者了解作者问的是什么对象吗?是的,我只是查看了列表API,我的错。所以基本上它可以作为列表收集,然后通过我提到的方法转换成数组。谢谢你的回复!您的解决方案都能工作,但它们都使用“传统”方法,我想它们比使用流慢。遗憾的是,以数组作为参数的数组不适用于泛型类型:((“无法创建列表的泛型数组”)我想我会坚持传统的方法。@Cl