Почему у java.util.Set нет (int index)?

Я уверен, что есть веская причина, но кто-то может объяснить, почему интерфейс java.util.Set не имеет get(int Index) или любого подобного метода get() ?

Кажется, что наборы отлично подходят для ввода вещей, но я не могу найти изящный способ извлечения одного элемента из него.

Если я знаю, что хочу первый элемент, я могу использовать set.iterator().next() , но в противном случае мне кажется, что я должен set.iterator().next() в массив для получения элемента по определенному индексу?

Каковы подходящие способы извлечения данных из набора? (кроме использования iteratorа)

Я уверен, что тот факт, что он исключен из API, означает, что есть хорошая причина не делать этого – может кто-нибудь, пожалуйста, просветить меня?

EDIT: Некоторые очень большие ответы здесь, а некоторые говорят «больше контекста». Конкретным сценарием был тест dbUnit, где я мог разумно утверждать, что возвращаемый набор из запроса имел только 1 элемент, и я пытался получить доступ к этому элементу.

Однако вопрос более важен без сценария, поскольку он по-прежнему более сфокусирован:

В чем разница между множеством и списком .

Спасибо всем за фантастические ответы ниже.

    Потому что наборы не имеют порядка. Некоторые реализации (в частности, реализующие интерфейс java.util.SortedSet ), но это не общее свойство множеств.

    Если вы пытаетесь использовать наборы таким образом, вам следует использовать вместо этого список.

    На самом деле это повторяющийся вопрос при написании приложений JavaEE, которые используют объектно-реляционное сопоставление (например, с Hibernate); и от всех людей, которые здесь ответили, Андреас Петерсон – единственный, кто понял настоящую проблему и предложил правильный ответ на это: Java не хватает UniqueList! (или вы также можете назвать его OrderedSet или IndexedSet).

    Maxwing упомянул этот прецедент (в котором вам нужны упорядоченные И уникальные данные), и он предложил SortedSet, но это не то, что действительно нужно Марти Питту.

    Этот «IndexedSet» не совпадает с SortedSet – в SortedSet элементы сортируются с использованием компаратора (или используя их «естественный» порядок).

    Но вместо этого он ближе к LinkedHashSet (что другие также предлагали), или, что еще более важно, к (также несуществующему) «ArrayListSet», потому что он гарантирует, что элементы будут возвращены в том же порядке, в каком они были вставлены.

    Но LinkedHashSet – это реализация, а не интерфейс! Нужен интерфейс IndexedSet (или ListSet, или OrderedSet или UniqueList)! Это позволит программисту указать, что ему нужен набор элементов с определенным порядком и без дубликатов, а затем создать экземпляр с любой реализацией (например, реализация, предоставляемая Hibernate).

    Поскольку JDK является открытым исходным кодом, возможно, этот интерфейс будет, наконец, включен в Java 7 …

    Просто добавив один пункт, который не упоминался в ответе mmyers .

    Если я знаю, что хочу первый элемент, я могу использовать set.iterator (). Next (), но в противном случае мне кажется, что я должен передать в массив для получения элемента по определенному индексу?

    Каковы подходящие способы извлечения данных из набора? (кроме использования iteratorа)

    Вы также должны ознакомиться с интерфейсом SortedSet (наиболее распространенная реализация которого – TreeSet ).

    SortedSet – это Set (т. Е. Уникальные элементы), который поддерживается упорядоченным естественным упорядочением элементов или использованием некоторого Comparator . Вы можете легко получить доступ к первому и последнему элементам, используя методы first() и last() . SortedSet пригодится каждый раз в то время, когда вам нужно сохранить свою коллекцию как без дубликатов, так и по заказу определенным образом.

    Изменить : если вам нужен набор, элементы которого хранятся в порядке вставки (подобно списку), взгляните на LinkedHashSet .

    Этот тип приводит к вопросу, когда вы должны использовать набор и когда вы должны использовать список. Обычно совет:

    1. Если вам нужны упорядоченные данные, используйте Список
    2. Если вам нужны уникальные данные, используйте набор
    3. Если вам нужны оба варианта, используйте либо: SortedSet (для данных, заказанных компаратором), либо OrderedSet / UniqueList (для данных, упорядоченных по вставке). К сожалению, Java API еще не имеет OrderedSet / UniqueList.

    Четвертый случай, который часто появляется, заключается в том, что вам не нужны ни то, ни другое. В этом случае вы видите, что некоторые программисты идут со списками, а некоторые – с наборами. Лично мне очень вредно видеть набор как список без заказа – потому что это действительно целый другой зверь. Если вам не нужны такие вещи, как уникальность набора или установление равенства, всегда пользуйтесь списками.

    Я не уверен, что кто-то изложил это именно так, но вам нужно понять следующее:

    В наборе нет элемента «first».

    Потому что, как говорили другие, наборы не имеют порядка. Набор представляет собой математическую концепцию, которая специально не включает упорядочение.

    Конечно, ваш компьютер не может хранить список вещей, которые не упорядочены в памяти. Он должен иметь некоторый порядок. Внутри это массив или связанный список или что-то в этом роде. Но вы действительно не знаете, что это такое, и на самом деле у него нет первого элемента; элемент, который выходит «первым», появляется случайно, и может быть не первый раз в следующий раз. Даже если вы предприняли шаги, чтобы «гарантировать» определенный первый элемент, он по-прежнему выходит случайно, потому что вы просто получили его право на одну конкретную реализацию Set; другая реализация может работать не так, как вы делали. И, на самом деле, вы, возможно, не знаете, какую реализацию вы используете, а также думаете, что делаете.

    Люди сталкиваются с этим ВСЕ. . ВРЕМЯ. с системами РСУБД и не понимают. Запрос RDBMS возвращает набор записей. Это тот же тип набора из математики: неупорядоченный набор элементов, только в этом случае элементы являются записями. Результат запроса RDBMS не имеет гарантированного порядка вообще, если вы не используете предложение ORDER BY, но все время люди предполагают, что он это делает, а затем когда-нибудь отключаются, когда форма их данных или кода слегка меняется и запускает оптимизатор запросов для работы по-другому, и внезапно результаты не выходят в ожидаемом порядке. Обычно это люди, которые не обращали внимания на class базы данных (или при чтении документации или учебников), когда им было объяснено, что результаты запроса не имеют гарантированного заказа.

    некоторые структуры данных отсутствуют в стандартных коллекциях java.

    Сумка (как набор, но может содержать элементы несколько раз)

    UniqueList (упорядоченный список, может содержать каждый элемент только один раз)

    кажется, вам понадобится uniquelist в этом случае

    если вам нужны гибкие структуры данных, вас могут заинтересовать Google Collections

    Это верно, элемент в Set не упорядочен, по определению Set Collection. Таким образом, они не могут получить доступ по индексу.

    Но почему мы не имеем метод get (object), а не предоставляем индекс как параметр, а объект, который равен тому, который мы ищем? Таким образом, мы можем получить доступ к данным элемента внутри Set, просто зная его атрибуты, используемые равным методом.

    Если вы собираетесь делать множество случайных запросов по индексу в наборе, вы можете получить представление массива его элементов:

     Object[] arrayView = mySet.toArray(); //do whatever you need with arrayView[i] 

    Однако есть два главных недостатка:

    1. Это не эффективность памяти, так как необходимо создать массив для всего набора.
    2. Если набор изменен, представление становится устаревшим.

    Это потому, что Set гарантирует уникальность, но ничего не говорит об оптимальных шаблонах доступа или использования. Т.е. набор может быть списком или картой, каждая из которых имеет очень разные характеристики поиска.

    Единственная причина, по которой я могу думать, что использовать числовой индекс в наборе, будет для итерации. Для этого используйте

     for(A a : set) { visit(a); } 

    Я столкнулся с ситуациями, когда на самом деле я хотел, чтобы отсортированный набор с доступом через индекс (я согласен с другими плакатами, что доступ к несортированному набору с индексом не имеет смысла). Примером может служить дерево, в котором я хотел бы, чтобы дети были отсортированы, а дублированные дети не были разрешены.

    Мне нужен был доступ через индекс, чтобы отображать их, а атрибуты набора были полезны для эффективного устранения дубликатов.

    Не найдя подходящую коллекцию в compilationах java.util или google, я нашел прямо ее реализовать. Основная идея состоит в том, чтобы обернуть SortedSet и создать Список, когда требуется доступ через индекс (и забыть список при изменении SortedSet). Это, конечно же, эффективно работает только при изменении обернутого SortedSet, и доступ к списку разделяется на время жизни коллекции. В противном случае он ведет себя как список, который сортируется часто, т.е. слишком медленный.

    С большим количеством детей эта улучшенная производительность намного превосходила список, который я отсортировал через Collections.sort.

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

    • Структуру данных массива можно получить через индекс с временной сложностью O(1) для достижения операции get(int index) .
    • Структуру данных LinkedList можно также получить через индекс, но с временной сложностью O(n) для достижения операции get(int index) .

    В Java ArrayList реализуется с использованием структуры данных Array .

    Хотя структура данных Set обычно может быть реализована через структуру данных HashTable / HashMap или BalancedTree , для быстрого обнаружения того, существует ли элемент и добавляет несуществующий элемент, обычно хорошо реализованный набор может достигать O(1) . В Java HashSet является наиболее распространенной используемой реализацией Set , она реализуется путем вызова HashMap API, а HashMap реализуется с использованием отдельной цепочки со связанными списками (комбинация Array и LinkedList ).

    Поскольку Set может быть реализован через другую структуру данных, для него нет метода get(int index) .

    Вы можете сделать new ArrayList(set).get(index)

    Причина, по которой интерфейс Set не имеет вызова типа индекса или даже чего-то еще более базового, например first () или last (), заключается в том, что это неоднозначная операция и, следовательно, потенциально опасная операция. Если метод возвращает Set, и вы вызываете, скажем, метод first () на нем, каков ожидаемый результат, учитывая, что общий набор не дает никаких гарантий при заказе? Результирующий объект может очень сильно различаться между каждым вызовом метода или не может и усыпить вас ложным чувством безопасности, пока библиотека, которую вы используете, не изменяет реализацию под ней, и теперь вы обнаружите, что все ваши разрывы кода для нет особой причины.

    Предложения об обходах, приведенные здесь, хороши. Если вам нужен индексированный доступ, используйте список. Будьте осторожны с использованием iteratorов или toArray с общим набором, потому что a) нет гарантии при заказе и b) нет гарантии, что порядок не изменится с последующими вызовами или с различными базовыми реализациями. Если вам нужно что-то среднее, то SortedSet или LinkedHashSet – это то, что вы хотите.

    // Я действительно хочу, чтобы интерфейс Set имел get-random-element.

    java.util.Set – это набор неупорядоченных элементов. Это не имеет никакого смысла, если Set имеет get (int index), потому что Set не имеет индекса, и вы можете только угадать значение.

    Если вы действительно этого хотите, запрограммируйте метод получения случайного элемента из Set.

    Если вы не возражаете, чтобы набор был отсортирован, вам может быть интересно взглянуть на проект с индексированной древовидной картой .

    Улучшенный TreeSet / TreeMap обеспечивает доступ к элементам по индексу или получение индекса элемента. И реализация основана на обновлении весов узлов в дереве RB. Таким образом, нет итераций или резервных копий здесь.

    Попробуйте этот код в качестве альтернативного варианта доступа через индексы

     import java.io.*; import java.util.*; class GFG { public static void main (String[] args) { HashSet  mySet=new HashSet(); mySet.add(100); mySet.add(100); int n = mySet.size(); Integer arr[] = new Integer[n]; arr = mySet.toArray(arr); System.out.println(arr[0]); } } 

    Это напечатает 100.

    Чтобы получить элемент в наборе, я использую следующий:

     public T getElement(Set set, T element) { T result = null; if (set instanceof TreeSet) { T floor = ((TreeSet) set).floor(element); if (floor != null && floor.equals(element)) result = floor; } else { boolean found = false; for (Iterator it = set.iterator(); !found && it.hasNext();) { if (true) { T current = it.next(); if (current.equals(element)) { result = current; found = true; } } } } return result; } 
    Давайте будем гением компьютера.