Итератор 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
}

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

5 8

5 ответов:

Java 8 представилапримитивные итераторы , которые позволяют избежать бокса/распаковки во время итерации по int, long и double коллекциям.

Вы можете создать собственный PrimitiveIterator в byte с typesafely реализации generic PrimitiveIterator<Byte,ByteConsumer>. ByteConsumer также должен быть реализован. И то и другое довольно прямолинейно.

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

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

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

Тогда вы можете использовать его следующим образом:

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

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

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

Реализуем итерацию и возвращаем байтовый объект вместо байтового примитива:

class Example implements Iterable<Byte> {

..

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

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

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

Если вы хотите, чтобы ваш итератор реализовывал java.утиль.Итератор next () должен будет вернуть байт

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

Remove также может быть реализован. Если вам не нужен имплемнентный итератор, то мы можем изменить next (), чтобы вернуть byte

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