Я уверен, что есть веская причина, но кто-то может объяснить, почему java.util.Set
отсутствует интерфейс get(int Index)
, или что-то подобноеget()
метод?
Кажется, что наборы отлично подходят для размещения вещей, но я не могу найти элегантный способ извлечь из него один предмет.
Если я знаю, что хочу первый элемент, я могу использовать set.iterator().next()
, но в противном случае мне кажется, что я должен привести к массиву для получения элемента по определенному индексу?
Каковы подходящие способы извлечения данных из набора? (кроме использования итератора)
Я уверен, что тот факт, что он исключен из API, означает, что есть веская причина этого не делать - может, кто-нибудь, пожалуйста, просветит меня?
РЕДАКТИРОВАТЬ: Некоторые очень хорошие ответы здесь, и некоторые говорят "больше контекста". Конкретным сценарием был тест dbUnit, где я мог обоснованно утверждать, что возвращенный набор из запроса содержал только 1 элемент, и я пытался получить доступ к этому элементу.
Однако вопрос более актуален без сценария, так как он остается более сфокусированным:
В чем разница между сетом и списком .
Спасибо всем за фантастические ответы ниже.
источник
Ответы:
Потому что наборы не имеют порядка. Некоторые реализации делают (особенно те, которые реализуют
java.util.SortedSet
интерфейс), но это не является общим свойством множеств.Если вы пытаетесь использовать наборы таким образом, вам следует рассмотреть возможность использования списка.
источник
На самом деле это повторяющийся вопрос при написании приложений JavaEE, которые используют объектно-реляционное сопоставление (например, с Hibernate); и из всех людей, которые ответили здесь, Андреас Петерссон - единственный, кто понял реальную проблему и предложил правильный ответ на нее: Java пропускает UniqueList! (или вы также можете назвать его OrderedSet или IndexedSet).
Максвинг упомянул этот вариант использования (в котором вам нужны упорядоченные И уникальные данные) и предложил SortedSet, но это не то, что действительно нужно Марти Питту.
Этот «IndexedSet» НЕ совпадает с «SortedSet» - в «SortedSet» элементы сортируются с использованием Comparator (или с использованием их «естественного» порядка).
Но вместо этого он ближе к LinkedHashSet (который также предлагали другие) или даже к (также несуществующему) «ArrayListSet», потому что он гарантирует, что элементы возвращаются в том же порядке, в котором они были вставлены.
Но LinkedHashSet - это реализация, а не интерфейс! Необходим интерфейс IndexedSet (или ListSet, или OrderedSet, или UniqueList)! Это позволит программисту указать, что ему нужна коллекция элементов, имеющих определенный порядок и без дубликатов, а затем создать его экземпляр для любой реализации (например, реализации, предоставленной Hibernate).
Поскольку JDK с открытым исходным кодом, возможно, этот интерфейс будет окончательно включен в Java 7 ...
источник
ListOrderedSet
то, что нужно ОП 7 лет назад (а мне нужно сегодня).What is needed is an IndexedSet (or ListSet, or OrderedSet, or UniqueList)...
и проигнорировал...interface
. Извини за это!Просто добавив один пункт, который не был упомянут в ответе mmyers .
Вы также должны ознакомиться с
SortedSet
интерфейсом (чья самая распространенная реализацияTreeSet
).SortedSet - это Set (то есть элементы уникальны), который упорядочен естественным упорядочением элементов или использованием некоторых
Comparator
. Вы можете легко получить доступ к первым и последним элементам, используяfirst()
иlast()
методы.SortedSet
Время от времени пригодится A , когда вам нужно сохранить свою коллекцию как без дубликатов, так и в определенной последовательности.Редактировать : если вам нужен набор, элементы которого хранятся в порядке вставки (очень похоже на список), взгляните на
LinkedHashSet
.источник
Этот вид приводит к вопросу, когда вы должны использовать набор и когда вы должны использовать список. Обычно совет идет:
Четвертый случай, который часто появляется, заключается в том, что вам не нужно ни того, ни другого. В этом случае вы видите, что некоторые программисты используют списки, а некоторые - наборы. Лично я считаю очень вредным видеть набор в виде списка без упорядочивания - потому что это действительно совсем другой зверь. Если вам не нужны такие вещи, как установить уникальность или установить равенство, всегда используйте списки предпочтений.
источник
Я не уверен, что кто-то излагал это именно так, но вы должны понимать следующее:
В наборе нет «первого» элемента.
Потому что, как уже говорили другие, наборы не имеют порядка. Набор - это математическая концепция, которая конкретно не включает в себя порядок.
Конечно, ваш компьютер не может хранить список вещей, которые не упорядочены в памяти. Это должно иметь некоторый порядок. Внутренне это массив или связанный список или что-то. Но вы на самом деле не знаете, что это такое, и у него нет первого элемента; элемент, который выходит «первым», появляется таким образом случайно и может не быть первым в следующий раз. Даже если вы предприняли шаги, чтобы «гарантировать» конкретный первый элемент, он все-таки вышел случайно, потому что вы просто случайно поняли его для одной конкретной реализации набора; другая реализация может не работать таким образом с тем, что вы сделали. И, на самом деле, вы можете не знать, какую реализацию вы используете, так, как вы думаете.
Люди сталкиваются с этим ВСЕМ. . ВРЕМЯ. с системами RDBMS и не понимаю. Запрос RDBMS возвращает набор записей. Это тот же тип набора из математики: неупорядоченный набор элементов, только в этом случае элементы являются записями. Результат запроса СУБД не имеет гарантированного порядка вообще, если только вы не используете предложение ORDER BY, но все время люди предполагают, что это происходит, и затем однажды теряют самообладание, когда форма их данных или кода изменяется незначительно и запускает работу оптимизатора запросов. другой путь, и внезапно результаты оказываются не в том порядке, в котором они ожидают. Обычно это люди, которые не обращали внимания в классе базы данных (или при чтении документации или учебных пособий), когда им заранее объясняли, что результаты запроса не имеют гарантированного порядка.
источник
Set
естьIterable
.некоторые структуры данных отсутствуют в стандартных коллекциях Java.
Сумка (как набор, но может содержать элементы несколько раз)
UniqueList (упорядоченный список, может содержать каждый элемент только один раз)
Кажется, в этом случае вам нужен уникальный список
если вам нужны гибкие структуры данных, вас могут заинтересовать Google Collections
источник
Это правда, что элементы в Set не упорядочены по определению Set Set. Таким образом, они не могут быть доступны по индексу.
Но почему у нас нет метода get (object), не предоставляя индекс в качестве параметра, а объект, который равен тому, который мы ищем? Таким образом, мы можем получить доступ к данным элемента внутри набора, просто зная его атрибуты, используемые равным методом.
источник
Если вы собираетесь делать много случайных обращений по индексу в наборе, вы можете получить представление массива его элементов:
Однако есть два основных недостатка:
источник
Это потому, что Set гарантирует только уникальность, но ничего не говорит об оптимальных моделях доступа или использования. То есть набор может быть списком или картой, каждая из которых имеет очень разные характеристики поиска.
источник
Единственная причина, по которой я могу использовать числовой индекс в наборе, - это итерация. Для этого используйте
источник
Я столкнулся с ситуациями, когда я действительно хотел отсортированный набор с доступом по индексу (я согласен с другими авторами, что доступ к несортированному набору с индексом не имеет смысла). Примером может служить дерево, где я хотел, чтобы дети сортировались, а дублировать детей не разрешалось.
Мне нужен был доступ через индекс для их отображения, а установленные атрибуты пригодились для эффективного устранения дубликатов.
Не найдя подходящей коллекции в java.util или в коллекциях google, я понял, что реализовать ее самому просто. Основная идея заключается в том, чтобы обернуть SortedSet и создать список, когда требуется доступ через индекс (и забыть список при изменении SortedSet). Это, конечно, эффективно работает только тогда, когда изменение упакованного SortedSet и доступ к списку разделены во время существования Коллекции. В противном случае он ведет себя как список, который сортируется часто, то есть слишком медленно.
С большим количеством детей это улучшило производительность по сравнению со списком, который я сортировал через Collections.sort.
источник
Обратите внимание, что только 2 основные структуры данных могут быть доступны через индекс.
O(1)
временной сложностью для достиженияget(int index)
операции.O(n)
трудоемкостью для достиженияget(int index)
операции.В Java
ArrayList
реализована структура данных Array .В то время как структура данных Set обычно может быть реализована через структуру данных HashTable / HashMap или BalancedTree , для быстрого определения, существует ли элемент и добавления несуществующего элемента, обычно хорошо реализованный Набор может достигнуть операции
O(1)
сложности времениcontains
. В JavaHashSet
является наиболее распространенной используемой реализацией Set , она реализуется посредством вызоваHashMap
API иHashMap
реализуется с использованием отдельного сцепления со связанными списками (комбинация Array и LinkedList ).Поскольку Set может быть реализован через другую структуру данных,
get(int index)
для него нет метода.источник
Data.Sequence.lookup
Функцию Хаскелла ) также позволяют получить доступ через индекс ( более точно ,O(1)
ближе к концамO(log n)
ближе к серединеO(min(log(k), log(n-k)))
), также как и двоичные деревья (см.Data.Set.lookupIndex
Функцию Хаскелла ). Таким образом, ваше первоначальное утверждение, что «Обратите внимание, что только две основные структуры данных могут быть доступны через индекс», неверно.Причина, по которой интерфейс Set не имеет вызова типа index или даже чего-то более простого, такого как first () или last (), заключается в том, что это неоднозначная операция и, следовательно, потенциально опасная операция. Если метод возвращает Set, и вы вызываете, скажем, метод first () для него, каков ожидаемый результат, учитывая, что универсальный Set не дает никаких гарантий относительно порядка? Результирующий объект может очень хорошо варьироваться между каждым вызовом метода, или он может и не вводить вас в заблуждение о безопасности, пока используемая вами библиотека не изменит свою реализацию, и теперь вы обнаружите, что весь ваш код прерывается для нет особой причины.
Предложения об обходных путях, перечисленные здесь, хороши. Если вам нужен индексированный доступ, используйте список. Будьте осторожны с использованием итераторов или toArray с универсальным множеством, потому что a) нет никакой гарантии на порядок и b) нет никакой гарантии, что порядок не изменится с последующими вызовами или с другими базовыми реализациями. Если вам нужно что-то промежуточное, вам нужен SortedSet или LinkedHashSet.
// Хотелось бы, чтобы интерфейс Set имел элемент get-random-element.
источник
java.util.Set
это коллекция неупорядоченных предметов. Это не имеет никакого смысла, если Set имеет get (int index), потому что Set не имеет индекса, а также вы можете только угадать значение.Если вы действительно этого хотите, закодируйте метод, чтобы получить случайный элемент из Set.
источник
Ты можешь сделать
new ArrayList<T>(set).get(index)
источник
new ArrayList<T>(t).get(0)
я думаю, что есть реальная оппозиция идее получения определенного элемента из набора по индексу. Но было бы неплохо, если бы Set имел функцию-член only (), которая для наборов размера 1 обеспечивала легкий доступ к единственному элементу в Set. Это спасло бы вышеупомянутоеnew ArrayList
илиfor (Foo foo : foos) { return foo; }
Если вы не возражаете против сортировки набора, вам может быть интересно взглянуть на проект indexed-tree-map .
Усовершенствованный TreeSet / TreeMap предоставляет доступ к элементам по индексу или получению индекса элемента. И реализация основана на обновлении весов узлов в дереве RB. Так что никакой итерации или резервного копирования по списку здесь.
источник
Set - это интерфейс, и некоторые из его классов реализации - HashSet, TreeSet и LinkedHashSet. Он использует HashMap для хранения значений. Поскольку HashMap не сохраняет порядок, получить значение по индексу невозможно.
Теперь вы должны подумать, как Set использует HashMap, поскольку HashMap хранит пару ключ-значение, а Set - нет. правильный вопрос когда вы добавляете элемент в Set, он поддерживает HashMap, где ключ - это элемент, который вы хотите ввести в Set, а значение - фиктивная константа. Ниже приведена внутренняя реализация функции добавления. Следовательно, все ключи в HashMap будут иметь одинаковое постоянное значение.
источник
Set
реализации используютсяHashMap
для хранения значений. Можете ли вы обосновать это утверждениеTreeSet
?the keys in the HashMap will have the same constant value
ключи вHashMap
карте будут отображаться на одном и том же неизменномObject
Чтобы получить элемент в наборе, я использую следующее:
источник
T
определяется? Почемуif (true)
?