2012-04-26 76 views
90

我有一個原始數組,例如int,int [] foo。它可能是小尺寸的,或者不是。將Java Array轉換爲Iterable

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

從它創建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> 

同時在回答前檢查 Why is an array not assignable to Iterable?

此外,如果您使用某些庫(例如番石榴),請解釋爲什麼這是最好的。 (因爲它來自谷歌不是一個完整的答案:P)

最後,因爲似乎有關於此功課,避免張貼家庭作業代碼。

+0

的可能重複[數組迭代器](http://stackoverflow.com/questions/3912765/iterator-for-array) – NPE 2012-04-26 14:38:57

+0

將它們添加到LinkedList,然後只返回該Set的迭代器。 – 2012-04-26 14:39:47

回答

77
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陣列)工作。

對於原語,用番石榴:

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

兩個注意事項:1)他有'int',而不是'Integer' 2)'List'已經是'Iterable',所以第三行是毫無意義的。 – maksimov 2012-04-26 14:51:25

+1

他需要Iterable,爲什麼有第三行。 – fmucar 2012-04-26 14:55:09

+1

那麼第二行是毫無意義的呢? ;) – maksimov 2012-04-26 15:03:09

33

只是我的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."); 
      } 
     }; 
    } 
}; 
+4

remove()在java 8中不是必需的,因爲它是引發UnsupportedOperationException的默認方法。只有當你想提供一個更好的解釋信息。 – Alex 2016-06-06 11:27:33

+0

+1我做了類似的事情,從'String'創建'Iterator '。實現自己的'Iterator'似乎是避免不必要地迭代所有值以將其從對象類型轉換爲基本類型(例如通過Guava的'Ints.asList()')的唯一方法,只是爲了能夠獲得一個來自List創建的'Iterator'。 – spaaarky21 2017-04-20 16:16:21

+1

你是對的Alex。 默認方法已添加到Java 8. 在2013年,我在這裏添加了這段古代代碼。 – 2017-10-18 17:31:07

19

番石榴提供你想要的Int.asList()適配器。有在相關類中的每個基本類型,例如Booleansboolean

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將無法​​正常工作,即使他們編譯,因爲你會得到一個Iterator<int[]>而不是Iterator<Integer>。會發生什麼情況是,不是創建一個由數組支持的列表,而是創建了一個包含數組的單元列表。

8

我有同樣的問題,解決它像這樣:

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

迭代器本身是一個懶惰的UnmodifiableIterator但是這正是我需要的。

3

首先,我只能認爲Arrays.asList(T...)顯然是Wrapper類型或數組類型非數據類型的最佳解決方案。該方法調用Arrays類中的簡單私有靜態AbstractList實現的構造函數,該類基本上將給定的數組引用保存爲字段,並通過覆蓋所需的方法來模擬列表。

如果你可以爲你的數組選擇一個初始類型或Wrapper類型,我會使用Wrapper類型來處理這種情況,當然,這並不總是有用或必需的。 將只有兩種可能性,你可以這樣做:

1)你可以創建一個類爲每個原始數據類型數組的一個靜態方法(boolean, byte, short, int, long, char, float, double返回一個Iterable< WrapperType >這些方法會使用的Iterator匿名類(除了Iterable)。允許將包含方法參數的引用(例如int[])作爲字段以便實現這些方法。

- >這種方法是高性能的並且可以節省您的內存(除了新創建的內存方法,即使使用Arrays.asList()也會以相同的方式佔用內存)

2)由於數組沒有方法(要在鏈接的那一邊讀取),它們也不能提供Iterator實例。如果你真的懶得寫新類,那麼你必須使用一個已經存在的類的實例來實現Iterable,因爲除了實例化Iterable或子類型之外沒有別的辦法。
創建實現Iterable的現有Collection衍生產品的唯一方法是使用循環(除非使用上述匿名類)或者實例化其構造函數允許使用原始類型數組的實現類(因爲Object[]不允許使用數組與原始類型的元素),但據我所知,Java API不具有這樣的類。

循環的原因可以很容易地解釋:
您需要的每個集合對象和原始數據類型不是對象。對象比原始類型大得多,因此它們需要額外的數據,這些數據必須爲基元類型數組的每個元素生成。這意味着,如果三種方式中的兩種(使用Arrays.asList(T...)或使用現有集合)需要聚合對象,則需要爲您的int[]數組的每個原始值創建包裝器對象。第三種方式將原樣使用該數組,並在匿名類中使用它,因爲我認爲它由於性能較快而更可取。

還有使用Object作爲論據要使用數組或Iterable,它需要類型檢查,以找出參數有哪些類型的方法的第三個策略,但我不會推薦它了因爲您通常需要考慮Object並不總是需要的類型,並且您需要在某些情況下使用單獨的代碼。

總之,這是Java有問題的泛型類型系統的缺陷,它不允許使用原始類型作爲通用類型,通過簡單地使用Arrays.asList(T...)可以節省大量代碼。因此,您需要爲每個基本類型數組編寫程序,這種方法(對於C++程序使用的內存基本上沒有區別,它會爲每個使用的類型參數創建一個單獨的方法。)

20

使用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(); 
-1

在java8 IntSteam流可以被裝箱到流整數。

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

我認爲,基於陣列的尺寸性能問題。使用ListOf

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

然後,你可以把它變成一個列表:

4

您可以使用IterableOfCactoos

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

或者簡單:

List<String> names = new ListOf<>(
    "Scott Fitzgerald", "Fyodor Dostoyevsky" 
); 
相關問題