Добавить значение к повторяемому - PullRequest
0 голосов
/ 01 марта 2019

Скажите, что у меня есть Iterable<T> iter, и скажите, что у меня есть Object v, который я хочу как-то добавить к Итерируемой.

У меня есть это, которое кажется неправильным:

var x = List.of(iter);
x.add(v);
return x.iterator();

вышеупомянутое не работает, потому что оно хочет, чтобы я сделал это вместо этого:

 var x = List.of(iter);
 x.add((Iterable<T>)v);
 return x.iterator();

почему это не позволяет мне сделать это?:

 var x = List.of(iter);
 x.add((T)v);   // does not compile, expects Iterable<T> not T
 return x.iterator();

Я должен делатьчто-то не так .. как мне подготовиться к Iterable?

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Причина, по которой вы не можете его скомпилировать, заключается в том, что в итоге вы получаете следующее (не используете var, поэтому типы легко видны).

List<Iterable<T>> x = List.of(iter); // List of Iterable<T> with a single element: "iter"
x.add(v); // Won't compile because "v" is an Object, not an Iterable<T>

x.add((Iterable<T>) v); // Compiles with warnings, will probably fail with ClassCastException at runtime

x.add((T) v); // Won't compile, "v" is being cast to "T" which is not an Iterable<T>

Несмотря на все это, List.of фабричные методы возвращают неизменяемые List.Даже если бы вы могли получить его для компиляции, вы получите UnsupportedOperationException, генерируемый во время выполнения.


Интерфейс Iterable не предоставляет никакого API для добавления элементов, только удаляя элементы черезIterator (если реализация поддерживает это).Это означает, что вы не можете добавить элемент к Iterable в общем смысле.Если вам нужен API, который предоставляет Iterable, вы можете добавлять элементы к вам, не следует возвращать Iterable для начала.Предпочитаю возвращать Collection или, так как вам нужно добавить элементы, List или Deque.Обратите внимание, что все упомянутые альтернативы простираются от интерфейса Iterable:

  • Итерируемый
    • Коллекция
      • Список
      • Набор
      • Очередь
        • Deque

Если по какой-либо причине необходимо вернуть Iterable, или проблема заключается всторонний API, тогда лучше всего создать копию и добавить в нее свои элементы.

Iterable<T> iter = ...;
Object v = ...;
List<Object> copy = new ArrayList<>();
copy.add(v); // add v first
iter.forEach(copy::add); // add rest of iterable after v

Обратите внимание, что List - это список Object сейчас.Вы указали, что у вас есть Iterable из T, к которому вы хотите добавить Object.Без дополнительной информации общий предок между этими двумя типами - Object.

Если вам не нужна копия, и вы знаете, что реализация Iterable является чем-то вроде модифицируемой List, вы можете разыграть, затем добавить:

((List<T>) iter).add(0, v); // in this case "v" must be of type "T"

Однако тот факт, что у вас есть Iterable, указывает на то, что созданный API не хочет и не ожидает, что он будет изменен вами, потребителемуказанный API.

0 голосов
/ 01 марта 2019

Он не позволяет вам сделать это:

var x = List.of(iter);
x.add((Iterable<T>)v);
return x.iterator();

Так как, я думаю, List x содержит объект типа (Iterable). Поэтому необходимо привести объект, который вы хотите добавить кСписок в этом типе: (итерируемый)

...