Java 在TreeSet中,排序和;基于不同特性的自定义对象的唯一性
下面是我的学生班Java 在TreeSet中,排序和;基于不同特性的自定义对象的唯一性,java,sorting,collections,treeset,unique,Java,Sorting,Collections,Treeset,Unique,下面是我的学生班 class Student implements Comparable { String name; int rollNo; @Override public int compareTo(Object obj) { return ((Student)obj).name.compareTo(this.name); } } 最新修改:但仍然没有得到正确的结果 @Override public int compareTo(Objec
class Student implements Comparable {
String name;
int rollNo;
@Override
public int compareTo(Object obj) {
return ((Student)obj).name.compareTo(this.name);
}
}
最新修改:但仍然没有得到正确的结果
@Override
public int compareTo(Object obj) {
Student s = (Student) obj;
if (name.equals(s.name)) { // achieving uniqueness
return 0;
} else {
if (rollNo < s.rollNo) {
return -1;
} else if (rollNo > s.rollNo) {
return 1;
} else {
// this makes `name` the second ordering option.
// names don't equal here
return name.compareTo(s.name);
}
}
}
朋友们,无论我用两个比较器得到什么,都可以
在添加对象时实现相同的效果??
我不能先添加元素,然后使用新的比较器来实现所需的顺序。
我正在处理成千上万的价值观,所以也需要考虑绩效。
您可以使用不同的比较器初始化新树集。-因此,您所要做的就是编写一个新的比较器(实现java.util.Comparator接口),使用这个比较器初始化一个新的树集,然后将所有学生添加到该集中
TreeSet<Student> sortedByRollNo new TreeSet<Student>(new RollNoComparator());
sortedByRollNo.addAll(allStudents);
TreeSet<Student> sortedByY new TreeSet<Student>(new YComparator());
sortedByY.addAll(allStudents);
TreeSet SortedByroll无新的TreeSet(新的RollNoComparator());
已分类的YROLLNO.addAll(所有学生);
TreeSet SortedBy new TreeSet(new YComparator());
SortedBy.addAll(所有学生);
每个树集都可以有自己的比较器进行排序,如果没有指定比较器,则树集使用集合元素的自然顺序
已添加
如果您只需要uniqe学生的名字,那么您有两种方法:
- 以某种方式实现比较器,如果studen的名称等于,它将返回0(但我相信这是一种黑客行为)
- 首先按姓名筛选学生,然后按编号排序
TreeSet<Student> sortedByRollNo new TreeSet<Student>(new RollNoComparator());
sortedByRollNo.addAll(new TreeSet<Student>(allStudends)); //this uses the native comparator to filter by uniqe name
TreeSet SortedByroll无新的TreeSet(新的RollNoComparator());
sortedByRollNo.addAll(新树集(所有studends))//这将使用本机比较器按uniqe名称进行筛选
在树集
中,它将使用比较器,同时添加元素进行排序和唯一性检查
现在的问题是,如果您对卷号使用比较器,您也将按卷号和唯一卷号对其进行排序。你不能在树上同时拥有这两个
我建议你去参加一个聚会
TreeSet
在这里,您将专注于重复删除ArrayList
,并按照您想要的顺序对其进行排序TreeSet
是一个好方法,请使用该方法
设计
您应该将“学生数据库”的概念封装在一个类中,该类公开并记录正确的行为,而不仅仅是使用原始集合。如果获得特定顺序的学生列表是设计要求,那么公开方法(可能返回Iterable
)就是这样。在幕后,您可以根据使用模式做各种事情:
- 维护一个或多个
s和/或Set
按兴趣领域对学生进行排序/索引map
- 使用
和指定的Arrays.sort()
比较器进行按需就地数组排序
final class StudentTable {
private static final Comparator<Student> studentRollNoComparator = ...;
private final SortedSet<Student> sortedByRollNo =
new TreeSet<Student>(studentRollNoComparator);
public Iterable<Student> studentsOrderedByRollNo()
{
return sortedByRollNo;
}
//see below
public void addStudent(final Student foo) { ... }
}
这样,插入学生的代码可以如下所示:
void addNewStudent(final Student toAdd)
{
if (studentSet.contains(toAdd)) {
throw new IllegalStateException("Student with same name as "+toAdd+" already exists.");
}
studentSet.add(toAdd);
}
然后,树集合中满是名称唯一的学生,如果没有,添加操作将报告失败。(引发异常只是一种可能的途径,并且只有在添加具有重复名称的学生实际上是一种例外情况时才合适,但您没有说。)很抱歉来晚了,这里有一个优雅的解决方案:
public class OwnSortedList<T> extends TreeSet<T> {
private static final long serialVersionUID = 7109828721678745520L;
public OwnSortedList(Comparator<T> levelScoreComparator) {
super(levelScoreComparator);
}
public boolean add(T e) {
boolean existsElement = false;
Iterator<T> it = iterator();
while(it.hasNext() && !existsElement){
T nextElement = it.next();
if(nextElement.equals(e)){
// Element found
existsElement = true;
Comparator<? super T> comparator = comparator();
int compare = comparator.compare(nextElement, e);
if(compare > 0){
remove(nextElement);
super.add(e);
//element added so return true
return true;
}
}
}
if(!existsElement){
super.add(e);
}
return false;
}
}
public类OwnSortedList扩展树集{
私有静态最终长serialVersionUID=7109828721678745520L;
公有SortedList(比较器级别Score比较器){
super(levelScoreComparator);
}
公共布尔加法(TE){
布尔existsElement=false;
迭代器it=迭代器();
while(it.hasNext()&&!existsElement){
T nextElement=it.next();
if(nextElement.equals(e)){
//元素发现
existsElement=true;
Comparator@org.life.java--什么是重复?你是说重复我的代码?但是如果我对RollNo使用comparator,它允许重复学生姓名。我需要对RollNo和唯一学生姓名进行排序。Ralph,你看到问题了吗,OP希望排序和唯一性都在一起好的,可以使用comparator(参见may扩展答案),但我不建议使用比较器进行筛选。是的,但在内部TreeSet不关心equals()&hashCode()如果名字不是唯一的,那么rollNo最高或最低的学生就剩下了,这很重要吗?我仍然不明白你期望得到什么样的结果。你能在你的例子中给出你的学生的期望顺序吗?TreeSet
在内部肯定关心equals()
和hashCode()
。阅读文档:如果学生姓名重复,您希望采取什么行为?自动放弃?报告?生活。java:非常聪明的答案:)但是,如果可能的话,你可以建议我扩展树集或创建实现集吗?如果可能的话,我想这样做,否则你的解决方案很好。@andersoj for TreeSet我们可以。如果这是唯一的情况,那么这将不会是一个问题,因为我们可以使用equals
和hashcode
以及排序com来处理唯一性parator
life.java,我的错,你是对的……然而,equals和hashcode应该在这里实现——它们只需要与comparator保持相等一致。
final class StudentTable {
private static final Comparator<Student> studentRollNoComparator = ...;
private final SortedSet<Student> sortedByRollNo =
new TreeSet<Student>(studentRollNoComparator);
public Iterable<Student> studentsOrderedByRollNo()
{
return sortedByRollNo;
}
//see below
public void addStudent(final Student foo) { ... }
}
final class Student implements Comparable {
...
@Override
public boolean equals(Object o)
{
return o!=null &&
o (instanceof Student) &&
((Student)o).name.equals(this.name);
}
@Override
public int hashCode()
{
return name.hashCode(); // good enough for this purpose
}
}
void addNewStudent(final Student toAdd)
{
if (studentSet.contains(toAdd)) {
throw new IllegalStateException("Student with same name as "+toAdd+" already exists.");
}
studentSet.add(toAdd);
}
public class OwnSortedList<T> extends TreeSet<T> {
private static final long serialVersionUID = 7109828721678745520L;
public OwnSortedList(Comparator<T> levelScoreComparator) {
super(levelScoreComparator);
}
public boolean add(T e) {
boolean existsElement = false;
Iterator<T> it = iterator();
while(it.hasNext() && !existsElement){
T nextElement = it.next();
if(nextElement.equals(e)){
// Element found
existsElement = true;
Comparator<? super T> comparator = comparator();
int compare = comparator.compare(nextElement, e);
if(compare > 0){
remove(nextElement);
super.add(e);
//element added so return true
return true;
}
}
}
if(!existsElement){
super.add(e);
}
return false;
}
}