2013-04-03 14 views
8

Ich habe eine Java-Klasse in der folgenden Form:Java Iterator für primitive Typen

class Example { 

    private byte[][] data; 

    public Example(int s) { data = new byte[s][s]; } 

    public byte getter(int x, int y)   { return byte[x][y]; } 
    public void setter(int x, int y, byte z) { byte[x][y] = z; } 
} 

Ich mag würde extern können, über die privaten Daten iterieren mit einem Iterator wie so:

for(byte b : Example) { ;/* do stuff */ }

ich habe versucht, eine private Iterator-Klasse zu implementieren, aber ich lief in Probleme:

private class ExampleIterator implements Iterator { 
    private int curr_x; 
    private int curr_y; 

    public ExampleIterator() { curr_x=0; curr_y=-1; } 
    public boolean hasNext() { 
    return curr_x != field.length-1 
     && curr_y != field.length-1; //is not the last cell? 
    } 
    public byte next() { // <-- Error is here: 
         // Wants to change return type to Object 
         // Won't compile! 
    if(curr_y=field.length) { ++curr_x; curr_y=0; } 
    return field[curr_x][curr_y]; 
    } 
    public void remove() { ; } //does nothing 
} 

Wie würde ich einen externen Iterator für primitive Typen (nicht Generika) implementieren? Ist das in Java möglich?

Antwort

5

Java 8 eingeführt primitive iterators, die Sie Boxen/Unboxing während der Iteration über int, lang und doppelt Sammlungen vermeiden lassen.

Sie können Ihre eigenen PrimitiveIterator von byte mit typesafely implementieren generische PrimitiveIterator<Byte,ByteConsumer>. ByteConsumer ist ebenfalls zu implementieren. Beide sind ziemlich einfach.

Warum gibt es keine PrimitiveIterator.ofByte in jdk? Wahrscheinlich wegen der Maschinenwortgröße, die normalerweise nicht kleiner als int ist. Oder Byte-Iteratoren werden besser von Streams und so gemacht.

+0

Gibt es für primitive Typen ein analoges 'Iterable', also kann ich' for (double d: myContainerWithDoubles) {} '? –

+0

Es gibt keinen for-each primitiven Iterator. Die beste Übereinstimmung besteht darin, 'PrimitiveIterator.OfDouble' zu ​​implementieren und auf funktionale Weise zu verwenden. – Oroboros102

8

Ein Iterator kann keine Werte eines primitiven Typs liefern. Es könnte jedoch Werte des Wrappertyps Byte ergeben. Solche Werte können auto-unboxed in byte sein (solange sie nicht null sind).

private class ExampleIterator implements Iterator<Byte> { 
    public boolean hasNext() { ... } 
    public Byte next() { ... } 
} 

Dann können Sie es wie so verwenden:

for (byte b : example) { ... } 
+0

Ich war mit dem Konzept des automatischen (un) boxens nicht vertraut. Hier kam meine Verwirrung her und wo sollte die Lösung gefunden werden. –

+0

@awashburn: Siehe http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html – NPE

+2

Normalerweise Autobox wie diese ist eine Möglichkeit, eine Menge Müll schnell zu generieren.Für "Byte" glaube ich jedoch, dass die meisten Java-Implementierungen ein Flightweight-Muster verwenden (da es nur 256 Byte-Werte gibt), so dass der GC keine zusätzliche Belastung darstellt. Beachten Sie jedoch, dass Sie 'for (byte b: instanceOfExample)' verwenden müssen - Sie können nicht über eine Klasse iterieren. –

0

Iterable implementieren und geben ein Byte-Objekt anstelle eines Byte primitiv:

class Example implements Iterable<Byte> { 

.. 

    public Iterator<Byte> iterator() { 
     return new MyIterator(); 
    } 

    private class MyIterator implements Iterator<Byte> { 
     public Byte next() {...} 
     .... 
    } 
} 

Implementierung Iterable statt Iterator ermöglicht es Ihnen, Schleifen der Objektelemente direkt mit der For-Each-Schleife.

1

Sie können keine Generics mit Primitiven verwenden, da die Generika eine Klasse für den Typ benötigen.

Was Sie tun können, ist über den Wrapper-Typen iterieren (Integer, Byte, Boolean, etc) ...

0

Wenn Sie Ihre Iterator java.util.Iterator dann next() zu implementieren, müssen zurückkehren Byte

class ByteArrayIterator implements Iterator<Byte> { 
    final byte[] a; 
    int i = 0; 
    ByteArrayIterator(byte[] a) { 
     this.a = a; 
    } 

    public boolean hasNext() { 
     return i < a.length; 
    } 

    public Byte next() { 
     if (i == a.length) { 
      throw new NoSuchElementException(); 
     } 
     return a[i++]; 
    } 

    public void remove() { 
     throw new UnsupportedOperationException(); 
    } 
} 

Entfernen kann auch implementiert werden. Wenn Sie es implemnent Iterator nicht brauchen, dann können wir als nächstes() ändern zurückzukehren Byte

class ByteArrayIterator { 
... 
    public byte next() { 
      if (i == a.length) { 
       throw new NoSuchElementException(); 
      } 
      return a[i++]; 
     } 
Verwandte Themen