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