2013-04-03 3 views
8

У меня есть класс Java следующего вида:Java Итератор для примитивных типов

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; } 
} 

Я хотел бы быть в состоянии внешне перебирать частные данные с использованием итератора так:

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

Я попытался реализовать частный класс итератора, но я столкнулся с проблемами:

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 
} 

Как бы реализовать внешний итератор для примитивных типов (не generics)? Возможно ли это на Java?

ответ

5

Java 8 введен primitive iterators, что позволит вам избежать бокс/распаковка во время итерации по междунар, длинные и двойные коллекции.

Вы можете создать свой собственный PrimitiveIterator из byte с типами реализующих общие PrimitiveIterator<Byte,ByteConsumer>. ByteConsumer также должен быть реализован. Оба они довольно просты.

Почему нет PrimitiveIterator.ofByte в jdk? Вероятно, из-за размера машинного слова, который обычно не меньше, чем int. Или байтовые итераторы лучше выполняются потоками и т. Д.

+0

Есть ли аналог 'Iterable' для примитивных типов, поэтому я могу сделать' for (double d: myContainerWithDoubles) {} '? –

+0

Для каждого примитивного итератора нет. Лучшее совпадение - реализовать 'PrimitiveIterator.OfDouble' и использовать его функционально. – Oroboros102

8

Итератор не может давать значения примитивного типа. Однако это может привести к значениям типа обертки Byte. Такие значения могут быть auto-unboxed в byte (при условии, что они не являются null).

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

Затем вы можете использовать его так:

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

Я был незнаком с концепцией авто- (un) бокса. Именно здесь возникла моя путаница и где было найдено решение. –

+0

@awashburn: см. Http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html – NPE

+2

Обычно автобоксинг подобен этому способу быстро генерировать много мусора.Однако для 'Byte', я считаю, что большинство реализаций Java используют шаблон flyweight (так как имеется только 256 байтовых значений), поэтому на GC нет дополнительной нагрузки. Обратите внимание, однако, что вам придется использовать 'for (byte b: instanceOfExample)' - вы не можете перебирать класс. –

0

Реализовать Iterable и возвращает объект Byte вместо байта примитивного:

class Example implements Iterable<Byte> { 

.. 

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

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

Реализация Iterable вместо Итератор позволяет вам для непосредственного обращения к объектам, используя цикл for-each.

1

Вы не можете использовать generics с примитивами, поскольку для генериков требуется класс для типа.

Что вы можете сделать, это перебрать типов Wrapper (Integer, Byte, Boolean, и т.д.) ...

0

Если вы хотите, чтобы ваш итератор для реализации java.util.Iterator то в следующем() будет возвращать Байт

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(); 
    } 
} 

удалить можно также. Если вам не нужно это implemnent итератора, то мы можем изменить следующий() возвращает байт

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