Are there any Java standard classes that implement Iterable without implementing Collection?
我有一个难题,让我思考是否有任何标准的Java类实现EDOCX1 0,而不需要实现EDCOX1 1。我正在实现一个接口,它要求我定义一个接受
这让我做了一些非常笨拙的感觉代码,在编译时给出一些未经检查的警告。
1 2 3 4 5 6 7 8 9 10 11 12 | public ImmutableMap<Integer, Optional<Site>> loadAll( Iterable<? extends Integer> keys ) throws Exception { Collection<Integer> _keys; if (keys instanceof Collection) { _keys = (Collection<Integer>) keys; } else { _keys = Lists.newArrayList(keys); } final List<Site> sitesById = siteDBDao.getSitesById(_keys); // snip: convert the list to a map |
将生成的集合更改为使用更通用的
在这个问题上似乎没有办法:其他问题在其他地方被问到,它似乎深深地植根于Java的泛型和类型删除系统中。但我想问的是,是否有任何类可以实现
我确信,由于我正在编写一些单元测试,我已经编写了与我在项目中使用的类型相关的强制转换或复制位。但是我想为一些输入编写一个单元测试,这些输入是一个不可迭代的集合,到目前为止,我所能想到的就是自己实现一个虚拟的测试类实现。
出于好奇,我正在实现的方法是guava的
虽然没有一个类可以立即满足您的需求,并且对测试代码的读者是直观的,但是您可以轻松地创建自己的匿名类,这很容易理解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | static Iterable<Integer> range(final int from, final int to) { return new Iterable<Integer>() { public Iterator<Integer> iterator() { return new Iterator<Integer>() { int current = from; public boolean hasNext() { return current < to; } public Integer next() { if (!hasNext()) { throw new NoSuchElementException(); } return current++; } public void remove() { /*Optional; not implemented.*/ } }; } }; } |
演示。
此实现是匿名的,不实现
克劳迪,是的,但我认为代码
1 2 3 4 5 6 | Collection<Integer> _keys; if (keys instanceof Collection) { _keys = (Collection<Integer>) keys; } else { _keys = Lists.newArrayList(keys); } |
完美无瑕。接口
综上所述,最后2段证明,如果某个东西既是一个
1 | @SuppressWarnings("unchecked") |
在声明上方。您还应该在注释中包含一个注释来解释为什么代码是安全的。
至于是否有实现
编辑
安德烈亚斯在评论中指出,EDCOX1的引用13只是在Java 5中引入的,而EDCOX1×2的引用是在Java 1.2中引入的,并且由于兼容的原因,无法使用EDOCX1×2的大多数现有方法进行EDCOX1 13的修改。
按标题回答问题:
Are there any Java standard classes that implement
Iterable without implementingCollection ?
从文本:
If there ever are any classes that can implement
Iterable that don't also implementCollection ?
答:
是的
请参见以下javadoc页面:https://docs.oracle.com/javase/8/docs/api/java/lang/class-use/iterable.html
任何表示EDCOX1(1)的部分都将列出实现接口的Java标准类。其中许多都没有实现
在核心API中,只有
1 2 3 4 5 6 7 8 | interface java.nio.file.Path interface java.nio.file.DirectoryStream interface java.nio.file.SecureDirectoryStream class java.util.ServiceLoader class java.sql.SQLException (and subclasses) |
可以说,这些都是不好的设计。
正如@ Buy.IO的回答中提到的那样,EDOCX1 13的一个实现是在Java 7中引入的文件系统遍历的新的EDCOX1×25类。
如果您恰巧在Java 8上,EDCOX1 OR 13(已经给出了EDCOX1×27方法)EDCOX1,28(注意它的实现注释),它允许您使用它与EDCOX1,29。
1 2 3 4 5 6 | public static <T> Collection<T> convert(Iterable<T> iterable) { // using Collectors.toList() for illustration, // there are other collectors available return StreamSupport.stream(iterable.spliterator(), false) .collect(Collectors.toList()); } |
这样做的代价很小,任何已经是
要对此进行测试,请考虑此代码段和示例输出:
1 2 3 4 |
在阅读了优秀的答案和提供的文档之后,我又在几节课上翻了翻,找到了看起来是赢家的东西,包括测试代码的直截了当性和直截了当的问题标题。Java的主要EDCOX1×0实现包含此GEM:
1 2 3 | public Iterator<E> iterator() { return new Itr(); } |
其中
最后一点,我的最终版本的代码甚至都不进行强制转换,因为guava的
1 2 3 4 5 6 7 8 9 10 11 12 | @GwtCompatible(serializable = true) public static <E> ArrayList<E> More ...newArrayList(Iterable<? extends E> elements) { checkNotNull(elements); // for GWT // Let ArrayList's sizing logic work, if possible if (elements instanceof Collection) { @SuppressWarnings("unchecked") Collection<? extends E> collection = (Collection<? extends E>) elements; return new ArrayList<E>(collection); } else { return newArrayList(elements.iterator()); } } |