Итератор 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 ответов:
Java 8 представилапримитивные итераторы , которые позволяют избежать бокса/распаковки во время итерации по int, long и double коллекциям.
Вы можете создать собственный
PrimitiveIteratorвbyteс typesafely реализации genericPrimitiveIterator<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++]; }