У меня есть массив примитивов, например для int, int [] foo. Это может быть маленький размер или нет.
int foo[] = {1,2,3,4,5,6,7,8,9,0};
Каков наилучший способ создать Iterable<Integer>
из него?
Iterable<Integer> fooBar = convert(foo);
Ноты:
Пожалуйста, не отвечайте с помощью циклов (если вы не можете дать хорошее объяснение того, как компилятор делает что-то умное с ними?)
Также обратите внимание, что
int a[] = {1,2,3};
List<Integer> l = Arrays.asList(a);
Даже не скомпилирует
Type mismatch: cannot convert from List<int[]> to List<Integer>
Также проверьте, почему массив нельзя назначить для Iterable? прежде чем ответить.
Кроме того, если вы используете какую-то библиотеку (например, Guava), пожалуйста, объясните, почему это лучше. (Потому что это от Google не полный ответ: P)
И последнее, так как кажется, что это домашнее задание, не размещайте домашний код.
Ответы:
Хотя вам нужно использовать
Integer
массив (неint
массив), чтобы это работало.Для примитивов вы можете использовать guava:
Для Java8: (из ответа Джин Квона)
источник
int
, а неInteger
2)List
ужеIterable
так третья строка бессмысленна.только мои 2 цента:
источник
Iterator<Character>
изString
. Реализация собственнойIterator
кажется единственным способом избежать ненужной итерации всех значений для преобразования из типа объекта в примитивный тип (например, через GuavaInts.asList()
), просто чтобы получить возможность получитьIterator
отList
созданного.С Java 8 вы можете сделать это.
источник
Guava предоставляет нужный адаптер в виде Int.asList () . Существует эквивалент для каждого типа примитива в связанном классе, например,
Booleans
дляboolean
и т. Д.Предложенные выше предложения
Arrays.asList
не будут работать, даже если они компилируются, потому что вы получаетеIterator<int[]>
вместоIterator<Integer>
. В результате получается, что вместо создания списка, поддерживаемого вашим массивом, вы создали 1-элементный список массивов, содержащий ваш массив.источник
У меня была такая же проблема, и я решил ее так:
Сам итератор ленив,
UnmodifiableIterator
но это именно то, что мне нужно.источник
В Java 8 или более поздней
Iterable
версии это функциональный интерфейс возвратаIterator
. Так что вы можете сделать это.источник
Прежде всего, я могу только согласиться с тем, что
Arrays.asList(T...)
это однозначно лучшее решение для типов или массивов Wrapper с не примитивными типами данных. Этот метод вызывает конструктор простой частной статическойAbstractList
реализации вArrays
классе, который в основном сохраняет заданную ссылку на массив как поле и моделирует список, переопределяя необходимые методы.Если вы можете выбирать между типом примитива или типом Wrapper для вашего массива, я бы использовал тип Wrapper для таких ситуаций, но, конечно, это не всегда полезно или необходимо. Вы можете сделать только две возможности:
1) Вы можете создать класс со статическим методом для каждого массива примитивных типов данных (
boolean, byte, short, int, long, char, float, double
возвращаяIterable<
WrapperType>
. Эти методы будут использовать анонимные классыIterator
(кромеIterable
), которые могут содержать ссылку на аргумент включающего метода (например, anint[]
) в качестве поля для реализации методов.-> Этот подход является быстродействующим и экономит вашу память (за исключением памяти вновь созданных методов, несмотря на то, что использование использовало
Arrays.asList()
бы память таким же образом)2) Поскольку у массивов нет методов (для чтения на стороне вы связались) они также не могут предоставить
Iterator
экземпляр. Если вам действительно лень писать новые классы, вы должны использовать экземпляр уже существующего класса, который реализует,Iterable
потому что нет другого пути, чем создание экземпляровIterable
или подтип.ЕДИНСТВЕННЫЙ способ создания существующей коллекции производной реализации
Iterable
должен использовать цикл (за исключением того, что вы используете анонимные классы, как описано выше) или вы создаете экземплярIterable
реализующего класса, конструктор которого допускает массив примитивного типа (потомуObject[]
что не допускает массивы с элементами примитивного типа), но, насколько я знаю, Java API не имеет такого класса.Причина цикла может быть легко объяснена:
для каждой Коллекции вам нужны Объекты, а первичные типы данных не являются объектами. Объекты намного больше, чем примитивные типы, поэтому им требуются дополнительные данные, которые должны быть сгенерированы для каждого элемента массива примитивных типов. Это означает, что если два способа из трех (использование
Arrays.asList(T...)
или использование существующей коллекции) требуют совокупности объектов, вам необходимо создать для каждого примитивного значения вашегоint[]
массив объекта обертки. Третий способ - использовать массив как есть и использовать его в анонимном классе, так как я думаю, что он предпочтительнее из-за высокой производительности.Существует также третья стратегия, использующая
Object
аргумент as для метода, в котором вы хотите использовать массив, илиIterable
требующая проверки типов, чтобы выяснить, какой тип имеет аргумент, однако я бы не рекомендовал его вообще, поскольку вам обычно требуется Учтите, что объект не всегда имеет требуемый тип, и вам нужен отдельный код для определенных случаев.В заключение, это вина проблематичной системы Generic Type, которая не позволяет использовать примитивные типы в качестве универсального типа, что позволило бы сэкономить много кода, просто используя
Arrays.asList(T...)
, Таким образом, вам нужно запрограммировать для каждого массива примитивного типа, вам нужен такой метод (который в принципе не имеет значения для памяти, используемой программой C ++, которая создаст для каждого используемого аргумента типа отдельный метод).источник
Вы можете использовать
IterableOf
от Cactoos :Затем вы можете превратить его в список, используя
ListOf
:Или просто так:
источник
Хотя подобный ответ уже был опубликован, я думаю, что причина использования нового PrimitiveIterator.OfInt не ясна. Хорошим решением является использование Java 8 PrimitiveIterator, поскольку он специализируется на примитивных типах int (и избегает дополнительных штрафов за упаковку / распаковку):
Ссылка: https://doc.bccnsoft.com/docs/jdk8u12-docs/api/java/util/PrimitiveIterator.OfInt.html
источник
В java8 поток IntSteam может быть упакован в поток целых чисел.
Я думаю, что производительность имеет значение в зависимости от размера массива.
источник