使用Java 8中的供应商填充具有通用列表的数组会抛出类型擦除的Cl
我想使用Supplier和Stream.generate将带有通用列表的数组填充为元素.
看起来像这样: Supplier<List<Object>> supplier = () -> new ArrayList<Object>(); List<Object>[] test = (List<Object>[]) Stream.generate(supplier).limit(m).toArray(); 错误输出为: Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.util.List; 现在,如何使用Java 8提供的技术填充具有泛型类型的数组?或者这是不可能的(还),我必须以“经典”的方式做到这一点? 问候, 编辑 根据@ 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 = 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); } } 正如你所看到的,Water确实是对的 – Cast让它变慢了. 解决方法
Stream生成器仍然生成你想要的对象,唯一的问题是调用toArray()将返回一个对象数组,并且你不能从Object数组向下转换为子对象数组(因为你有类似的东西: 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)); } 如果您正在设置处理该功能,您可以执行以下操作: 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)); } 根据Stream Javadocs你可以使用另一个toArray()方法,如果你想把它变成一个数组,但我还没有探索过这个函数,所以我不想讨论一些我不知道的事情. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |