如果我想检索和更新存储在TreeSet中的对象怎么办?
我问的原因是,我希望能够保留一些可以存储学生的数据结构。 我希望它被排序(按成绩 - 这是学生的实例变量),并且 - 即使在我更新了一个(或多个)成绩之后,它也需要保持排序。
因此,在简要查看了Java的集合之后,我决定使用TreeSet并设置一个比较器,按比例对两个学生进行比较。 问题是,我刚发现TreeSet没有get()方法!
非常感谢任何帮助和建议。
答案 0 :(得分:26)
您希望get()
上的Set
方法做什么?
get(int index)
毫无意义。 (如果您想按索引获取元素,请使用List
。get(Object obj)
也没有意义,因为你已经拥有了你想要获得的对象。contains()
方法检查Set
是否包含对象。Set
。答案 1 :(得分:11)
您可以使用Iterator从树集中检索元素。你可以尝试这样的事情:
Iterator<Integer> it = treeSet.iterator();
Integer current = 0;
while(it.hasNext() ) {
current = it.next();
}
希望这有帮助。
答案 2 :(得分:4)
我确实有一个使用两个TreeSets的情况(因为它们在搜索中速度更快)。其中一棵树是巨大的,树中的对象是不同的,所以我创建了一个模拟对象(类型2,第二个树),它具有用于排序的字段,使用来自小树的对象的数据并检查是否第二个是对手。现在我需要检查第二个树中找到的对象的值,以便在报告上添加值。
使用迭代器而不是二进制搜索来检索我需要的对象,这违背了使用二叉树的目的。第二棵树是5GB加,找到第一棵树(200MB)中的数据匹配。我需要一个对大量数据有意义的搜索策略,因此我选择了二进制搜索树。参赛作品是独一无二的。
答案 3 :(得分: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;
}
不要忘记重载Student类中的equals和hashcode以使其正常工作。
如果您想要轻松快速地执行java索引编制,您可能还需要检查cqengine库,但上面提供的解决方案可以满足您的使用。
答案 4 :(得分:1)
您可以迭代树以检索其对象。 NavigableSet怎么样?有短途导航的方法,如
E ceiling(E e) E floor(E e)
E higher(E e) E lower(E e)
答案 5 :(得分:1)
TreeSet
在插入时排序。如果您按照学生的成绩订购并在添加后修改它们,则不再对这些项目进行排序(与之前的顺序相同)。
TreeSet
也不使用equals()
来确定是否已添加元素,而是使用比较器(相同的顺序=相同的项目)。因此,如果两个学生的成绩相同,则只添加其中一个。来自Javadoc:
TreeSet实例使用compareTo执行所有元素比较 (或比较)方法,因此两个被认为相等的元素 从集合的角度来看,方法是相等的。
您可以使用TreeSet
和在需要时按年级对学生进行排序(创建包含学生的新列表,对其进行排序和排序),而不是使用HashSet
。迭代它。)
答案 6 :(得分:1)
如果它包含确切的对象,则地板将返回您要查找的确切对象。
if(set.contains(searchingObject)) {
addonPartNumber = p.floor(searchingObject);
}
答案 7 :(得分:1)
确实没有通过引用获取或通过索引获取的方法。但是,有一种简单的方法可以构建按引用获取方法。
可以使用方法boolean contains(E input)
和E ceiling(E input)
来实现。实际上,根据Javadoc的ceiling方法:
返回此集合中的最小元素大于或等于 给定的元素,如果没有这样的元素,则为{@code null}。
因此,如果我们事先知道该元素在集合中,则可以保证调用ceiling会返回与输入相等的元素。
import java.util.Comparator;
import java.util.TreeSet;
public class ExtendedTreeSet<E> extends TreeSet<E> {
public ExtendedTreeSet(Comparator<? super E> comparator) {
super(comparator);
}
public E get(E input) {
return this.contains(input) ? this.ceiling(input) : null;
}
}
答案 8 :(得分:0)
您也可以使用for-each获取TreeSet
内的所有元素。
TreeSet<String> words = new TreeSet<String>();
for(String w : words) {
System.out.println(w);
}
您可以执行迭代,将TreeSet
中的唯一字词复制到列表中,这样您就有权使用get();
希望,它有所帮助。
答案 9 :(得分:0)
这是我为自己找到的问题的答案,但我认为套装应该有get(elem)
,但正如您所知,没有。
你走了:
set.subSet(elem,true,elem,true).floor(elem);
这会返回第一个对象,它等于您正在寻找的对象。
注意强>: elem 必须与您要查找的元素相等,并且您获得所需的对象 OR 将比较器分配给匹配它们的集合 equals
我很惊讶以前没有人想过它。
需要竖起大拇指:D
答案 10 :(得分:0)
通过键(在这种情况下是键和值相同)获取元素的最有效方法是:
A get(A a)
{
var res = tree.floor(a);
if (a.compareTo(res) == 0)
{
return res;
}
return null;
}