将Java Array转换为Iterable

我有一个原始数组,例如int,int [] foo。 它可能是一个小尺寸的,或不。

int foo[] = {1,2,3,4,5,6,7,8,9,0}; 

什么是从它创build一个Iterable<Integer>的最好方法?

 Iterable<Integer> fooBar = convert(foo); 

笔记:

请不要回答使用循环(除非你可以给出一个很好的解释,如何编译器做一些聪明的事情?)

另请注意

 int a[] = {1,2,3}; List<Integer> l = Arrays.asList(a); 

甚至不会编译

 Type mismatch: cannot convert from List<int[]> to List<Integer> 

另外检查为什么数组不能分配给Iterable? 在回答之前。

另外,如果你使用一些图书馆(例如番石榴),请解释为什么这是最好的。 (因为它来自Google不是一个完整的答案:P)

最后,由于似乎有一个功课,避免张贴家庭作业代码。

 Integer foo[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; List<Integer> list = Arrays.asList(foo); // or Iterable<Integer> iterable = Arrays.asList(foo); 

虽然你需要使用Integer数组(而不是一个int数组)来实现这个function。

对于基元,使用番石榴:

 Iterable<Integer> fooBar = Ints.asList(foo); 
 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>15.0</version> <type>jar</type> </dependency> 

只是我2美分:

 final int a[] = {1,2,3}; java.lang.Iterable<Integer> aIterable=new Iterable<Integer>() { public Iterator<Integer> iterator() { return new Iterator<Integer>() { private int pos=0; public boolean hasNext() { return a.length>pos; } public Integer next() { return a[pos++]; } public void remove() { throw new UnsupportedOperationException("Cannot remove an element of an array."); } }; } }; 

Guava提供了你想要的适配器Int.asList() 。 每个关联类中的基本types都有一个等价的,例如Booleans等的Booleans boolean

 int foo[] = {1,2,3,4,5,6,7,8,9,0}; Iterable<Integer> fooBar = Ints.asList(foo); for(Integer i : fooBar) { System.out.println(i); } 

上面使用Arrays.asList的build议将不起作用,即使它们是因为您获得Iterator<int[]>而不是Iterator<Integer>而编译的。 会发生什么事,而不是创build一个由数组支持的列表,您创build了一个包含数组的单元列表。

用Java 8,你可以做到这一点。

 final int[] arr = {1, 2, 3}; final PrimitiveIterator.OfInt i1 = Arrays.stream(arr).iterator(); final PrimitiveIterator.OfInt i2 = IntStream.of(arr).iterator(); final Iterator<Integer> i3 = IntStream.of(arr).boxed().iterator(); 

我有同样的问题,并解决这个问题:

 final YourType[] yourArray = ...; return new Iterable<YourType>() { public Iterator<YourType> iterator() { return Iterators.forArray(yourArray); // Iterators is a Google guava utility } } 

迭代器本身是一个懒惰的UnmodifiableIterator但这正是我所需要的。

您可以使用ArrayAsIterable的ArrayAsIterable :

 Iterable<String> names = new ArrayAsIterable<>( "Scott Fitzgerald", "Fyodor Dostoyevsky" ); 

然后,你可以使用IterableAsList把它变成一个列表:

 List<String> names = new IterableAsList<>( new ArrayAsIterable<>( "Scott Fitzgerald", "Fyodor Dostoyevsky" ) ); 

首先,我只能同意Arrays.asList(T...)显然是Wrappertypes或数组types非数据types的最佳解决scheme。 这个方法在Arrays类中调用一个简单的私有静态AbstractList实现的构造函数,它基本上将给定的数组引用保存为字段,并通过覆盖所需的方法来模拟列表。

如果你可以为数组select一个初始types或者一个Wrappertypes,我会使用Wrappertypes来处理这种情况,当然,这并不总是有用或者是必需的。 只有两种可能:

1)你可以为每个原始数据types数组( boolean, byte, short, int, long, char, float, double )创build一个类,这些方法会使用匿名类的Iterator (除了Iterable ),为了实现这些方法,它允许包含包含方法参数的引用(例如int[] )作为字段。

– >这种方法是高性能的,可以节省你的内存(除了新创build的方法的内存外,即使使用Arrays.asList()也会以相同的方式占用内存)

2)由于数组没有方法(在链接的一面读取),它们也不能提供Iterator实例。 如果你真的懒得编写新的类,你必须使用一个已经存在的实现了Iterable类的实例,因为除了实例化Iterable或者子types之外没有别的办法。
创build实现Iterable的现有集合衍生物的唯一方法是使用循环(除了使用上面描述的匿名类)或者实例化一个Iterable实现类,该类的构造方法允许使用原始types数组(因为Object[]不允许使用数组与原始types元素),但据我所知,Java API不具有这样的类。

循环的原因可以很容易地解释:
为每个集合你需要对象和原始数据types不是对象。 对象比基本types要大得多,因此它们需要额外的数据,这些数据必须为基本types数组的每个元素生成。 这意味着如果三种方法(使用Arrays.asList(T...)或使用现有的Collection)需要聚合对象,则需要为每个int[]数组的原始值创build包装器对象。 第三种方式将原样使用数组,并在一个匿名类中使用它,因为我认为由于性能较快,所以它是可取的。

还有一个使用Object作为参数的第三个策略,您想要使用该数组或Iterable ,需要进行types检查来确定参数的types,但是我不会像通常那样推荐它需要考虑到Object并不总是需要的types,并且在某些情况下你需要单独的代码。

总之,这是Java有问题的genericstypes系统的错误,它不允许使用原始types作为通用types,通过使用Arrays.asList(T...)可以节省大量的代码。 所以你需要为每个原始types数组编写程序,你需要一个这样的方法(这对于C ++程序使用的内存基本上没有什么区别,它会为每个使用的types参数创build一个独立的方法。

 int foo[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; PrimitiveIterator.OfInt intIterator = Arrays.stream(foo).iterator(); Iterator<Integer> iterator = intIterator; 

在java8中,IntSteamstream可以被装箱到整数stream。

 public static Iterable<Integer> toIterable(int[] ints) { return IntStream.of(ints).boxed().collect(Collectors.toList()); } 

我认为性能基于数组的大小很重要。