将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()); }
我认为性能基于数组的大小很重要。