У меня проблемы с пониманием того, как я не могу найти getLength() итерации в моей домашней работе. Предполагается, что класс представляет собой «набор инструментов» с полезными методами для работы с итерируемыми объектами и итераторами.
/** Computes the length of an Iterable.
The length of an Iterable is the total number of entries it returns.
public static <T> int getLength(Iterable<T> iterable)
{
int numEntries = 0;
while(iterable.hasNext()) {
numEntries++;
iterable.next();
}
return numEntries;
}
Это то, что у меня есть сейчас, но я получаю это
Toolkit.java:30: error: cannot find symbol
while(iterable.hasNext()) {
^
symbol: method hasNext()
location: variable iterable of type Iterable<T>
where T is a type-variable:
T extends Object declared in method <T>getLength(Iterable<T>)
^ И сохраните полученный Iterator
в переменной, чтобы вы могли использовать его в цикле while.
Кроме того, я не знаю, была ли вам предоставлена сигнатура метода, но параметр типа (<T>
) не обязателен. Метод не зависит от типа элементов в итерируемом объекте, поэтому параметр метода может быть просто Iterable<?>
.
Или for (T dummy : iterable) numEntries++;
.
Попробуй это:
public static int size(`Iterable` data) {
if (data instanceof Collection) {
return ((Collection<?>) data).size();
}
int counter = 0;
for (Object i : data) {
counter++;
}
return counter;
}
Это концептуально не работает. Концепция Iterable
заключается исключительно в том, что вы можете попросить его создать итераторы. Именно итератор отвечает за все hasNext
и next
. Итераторы не гарантируют, что они будут возвращать один и тот же итератор каждый раз, когда вы запрашиваете итератор; вы можете вызвать iterator()
и увидеть 500 элементов, а затем снова вызвать и увидеть 512. У вас нет особых гарантий, поэтому «запросить длину итерации» не подлежит ответу. Для некоторых конкретных известных итераций, таких как ArrayList
, вы можете ответить на вопрос, и это будет легко сделать, но есть итерации, для которых вы не можете этого сделать. Различные итерации могут быть запрошены только один раз для iterator()
, например, что-либо, представляющее концепцию потоковой передачи (скажем, ваша итерация — это пожарный шланг всех сообщений телеграммы, отправленных на канал телеграммы).
Другими словами, это глупая домашняя работа; кто бы это ни дал, не до конца понимает, что представляют собой эти понятия. Этот код будет работать для некоторых итераций, но не будет работать для многих других, либо делая недействительной возможность итерации через него после вызова этого, либо сбой, либо давая неправильный ответ - это именно то, что вы написали, за исключением того, что сначала создайте итератор. Пока мы здесь, давайте избавимся от этого бесполезного <T>
, он нам не нужен:
public static int getLength(Iterable<?> iterable) {
int numEntries = 0;
var iterator = iterable.iterator();
while(iterator.hasNext()) {
numEntries++;
iterator.next();
}
return numEntries;
}
Однако, учитывая, что на самом деле это не «работает», я бы написал что-то совсем другое:
public static int getLength(Iterable<?> iterable) throws IllegalArgumentException {
if (iterable instanceof Collection<?>) return ((Collection<?>) iterable).size();
throw new IllegalArgumentException("I don't know how to obtain the size for an iterable of type " + iterable.getClass());
}
Действительно, ошибка во всей установке является аргументом. Так должно было быть Collection<?>
все это время. Почти все итерации, которые вы когда-либо встречали, реализуют Collection
— основное различие между Iterable и Collection в том, что вы можете спросить у коллекции, насколько она велика. Iterable существует именно потому, что он представляет собой тип, в котором «могу ли я узнать, насколько вы велики» не является обязательной способностью. Еще раз подчеркнув, насколько глупо это домашнее задание.
Не стесняйтесь направлять своего учителя к этому ответу. Если это общий учебник или книга, выбросьте ее и возьмите другую.
Вы должны вызвать
Iterable.iterator()