2013-12-03 3 views
17

Что делать, если я хочу получать и обновлять объекты, хранящиеся в TreeSet?Почему Java TreeSet не имеет метода get()?

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

Итак, после краткого изучения коллекций Java, я решил пойти с TreeSet и установить компаратор, который сравнивает двух студентов по их классам. проблема в том, что я только что узнал, что TreeSet не имеет метода get()!

Любая помощь и предложения были бы весьма признательны.

ответ

23

Что вы ожидаете от метода get() на Set?

  • Наборы не проиндексированы, поэтому get(int index) не имеет смысла. (Используйте List, если хотите получить элементы по индексу).
  • get(Object obj) также не имеет смысла, потому что у вас будет объект, который вы пытаетесь получить уже.
  • У вас уже есть метод , чтобы проверить, содержит ли объект Set объект.
  • Вы можете выполнить итерацию по Set, если хотите что-то сделать со всеми элементами в наборе.
+2

Только то, что я хотел написать: +1. За исключением индексированного случая: вместо «не имеет смысла» я бы написал «использовать« Список » –

+0

Или использовать« Карта »для хранения объектов на основе некоторого ключа. –

+0

Спасибо за помощь. Итак, какие у меня варианты? –

8

Вы можете извлечь элементы из дерева с помощью Итератора. Вы можете попробовать что-то вроде этого:

Iterator<Integer> it = treeSet.iterator(); 

Integer current = 0; 
while(it.hasNext()) { 
current = it.next(); 

} 

Надеюсь, это поможет.

1

Вы можете выполнить итерацию дерева для извлечения его объектов. Как насчет NavigableSet? существуют методы навигации на короткие расстояния, как

E ceiling(E e) E floor(E e) 
E higher(E e) E lower(E e) 
1

TreeSet является отсортированные при вставке. Если вы заказываете по классам учащихся и изменяете их после добавления, элементы больше не сортируются (в том же порядке, что и раньше).

TreeSet также не использует equals(), чтобы определить, добавлен ли элемент, но вместо этого использует компаратор (тот же порядок = тот же элемент). Поэтому, если у двух учеников одинаковые оценки, добавляется только один из них. От Javadoc:

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

Вместо использования TreeSet, вы можете использовать HashSet и отсортировать студентов по классам, когда вам нужно их (создать новый список, содержащий студентов, сортировки и итерацию по ней).

+0

Так что в принципе нет реального способа сделать это динамически. –

+1

По крайней мере, не используя стандартные коллекции. Пока упорядочение может быть произвольным (любая реализация Comparator или Comparable), сборник должен был бы * наблюдать * содержащиеся объекты для изменений. Для этого потребуется два интерфейса: один для наблюдаемых (реализуемых объектами) и один для наблюдателя (интерфейс слушателя с методом обратного вызова для наблюдателя, который является коллекцией). –

3

Как правило, вы не захотите получить элемент в наборе, если у вас уже есть его. Вы можете удалить свой элемент из набора или узнать, принадлежит ли он к набору, вот и все. Знайте, что хотите, чтобы вы указали своих учеников по классам, поэтому индекс - это класс, а не сам объект. Карта - это решение.

Если бы я тебя, я хотел бы использовать следующую структуру, которая извлекает все студенты с же класса быстро (они сортируются по классам тоже):

private SortedMap<Integer,Set<Student>> _studentsByGrade = new TreeMap<Integer,Set<Student>>(); 

public void updateStudent(Student student, int oldGrade, int newGrade) 
{ 
    getOrCreateContainer(oldGrade).remove(student); 
    getOrCreateContainer(newGrade).add(student); 
    student.setGrade(newGrade); 
} 

public Set<Student> getOrCreateContainer(int grade) 
{ 
    Set<Student> set = _studentsByGrade.get(grade); 
    if(set==null) 
    { 
    set = new HashSet<Student>(); 
    _studentsByGrade.put(grade, set); 
    } 
    return set; 
} 

Не забудьте перегрузить равных и hashcode в вашем классе Student, чтобы он работал правильно.

Возможно, вы также захотите проверить библиотеку cqengine, если вы хотите быстро и быстро выполнить индексацию java, но представленное выше решение просто подходит для вашего использования.

0

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

TreeSet<String> words = new TreeSet<String>(); 
for(String w : words) { 
    System.out.println(w); 
} 

Вы можете выполнить итерацию, чтобы скопировать уникальные слова из TreeSet в списках, что дает привилегию использовать get();

Надежда, это помогло.

4

У меня есть случай, когда я использую два TreeSets (потому что они быстрее в поиске). Одно из этих деревьев огромно, а объекты в деревьях разные, поэтому я создаю макет объекта (типа 2, второе дерево), который имеет поля, используемые для сортировки, используя данные из объекта из маленького дерева и проверяем, на втором есть аналог. Теперь мне нужно проверить значение из объекта, найденного во втором дереве, чтобы добавить значение в отчет.

Использование итератора вместо бинарного поиска для извлечения требуемого объекта поражает цель использования двоичного дерева. Второе дерево - 5 ГБ плюс, поиск совпадений с данными в первом дереве (200 МБ). Мне нужна стратегия поиска, которая имеет смысл для этого огромного количества данных, поэтому я выбрал дерево двоичного поиска. Записи уникальны.

Смежные вопросы