Student.java:
package oop01;
public class Student{
private int id;
private String name;
private int age; public Student() {
} public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String toString() {
return this.id + "\t" + this.name + "\t" + this.age;
} @Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
=======================================================================================
AgeDesc.java:
package oop01;
import java.util.Comparator;
public class AgeDesc implements Comparator{
public int compare(Object o1,Object o2){
Student s1=(Student)o1;
Student s2=(Student)o2;
if(s1.getAge()==s2.getAge()){
return 0;
}
return s1.getAge()>s2.getAge()?1:-1;
}}
=======================================================================================
测试类:Demo02.java:
package oop01;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class Demo02 {
public static void main(String[] args) {
AgeDesc ad=new AgeDesc();
Set set=new TreeSet(ad);
Student s1=new Student(001,"jim",21);
Student s2=new Student(002,"tom",21);
Student s3=new Student(003,"lucy ",21);
Student s4=new Student(004,"lili",21);
Student s5=new Student(004,"lili",21);
set.add(s1);
set.add(s2);
set.add(s3);
set.add(s4);
set.add(s5);
Iterator itor=set.iterator();
while(itor.hasNext()){
System.out.println(itor.next());
}
}}
=======================================================================================
运行结果:
1 jim 21=======================================================================================
大家帮我解释一下吧,本人java基础不咋的:我需要详细的解释,和解决方法。
TreeSet和TreeMap的源码已经看过了,知道是TreeMap中的put方法中的else块中的setValue方法惹的祸。只是现在我想找解决方法。目前比较被动的解决方法是改写AgeDesc类的compare方法:
public int compare(Object o1,Object o2){
Student s1=(Student)o1;
Student s2=(Student)o2;
if(s1.equals(s2)){
return 0;
}
return s1.getAge()>s2.getAge()?1:-1;
}
package oop01;
public class Student{
private int id;
private String name;
private int age; public Student() {
} public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String toString() {
return this.id + "\t" + this.name + "\t" + this.age;
} @Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
=======================================================================================
AgeDesc.java:
package oop01;
import java.util.Comparator;
public class AgeDesc implements Comparator{
public int compare(Object o1,Object o2){
Student s1=(Student)o1;
Student s2=(Student)o2;
if(s1.getAge()==s2.getAge()){
return 0;
}
return s1.getAge()>s2.getAge()?1:-1;
}}
=======================================================================================
测试类:Demo02.java:
package oop01;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class Demo02 {
public static void main(String[] args) {
AgeDesc ad=new AgeDesc();
Set set=new TreeSet(ad);
Student s1=new Student(001,"jim",21);
Student s2=new Student(002,"tom",21);
Student s3=new Student(003,"lucy ",21);
Student s4=new Student(004,"lili",21);
Student s5=new Student(004,"lili",21);
set.add(s1);
set.add(s2);
set.add(s3);
set.add(s4);
set.add(s5);
Iterator itor=set.iterator();
while(itor.hasNext()){
System.out.println(itor.next());
}
}}
=======================================================================================
运行结果:
1 jim 21=======================================================================================
大家帮我解释一下吧,本人java基础不咋的:我需要详细的解释,和解决方法。
TreeSet和TreeMap的源码已经看过了,知道是TreeMap中的put方法中的else块中的setValue方法惹的祸。只是现在我想找解决方法。目前比较被动的解决方法是改写AgeDesc类的compare方法:
public int compare(Object o1,Object o2){
Student s1=(Student)o1;
Student s2=(Student)o2;
if(s1.equals(s2)){
return 0;
}
return s1.getAge()>s2.getAge()?1:-1;
}
解决方案 »
- 关于JAVA内存 方面的疑问。
- 问一个关于IllegalMonitorStateException的问题
- 请教一下java的类反射和类装载器。能说一下他们的用处和他们有什么相同的吗???没分了,只能给这么多了
- 网络文件传送出现问题,,大家帮忙看看!!!!!
- 谁来给我讲讲java的守护线程是怎么一回事?100分相赠
- 我想把一个表里的数据拿出来,转换成xml格式,通过网络传到另外的数据消费者,如何设计xml的格式
- 我想将一个JButton加上图标,可是下面的语句确不能实现,我改怎么办呢?100分等着你!!
- 听说,初学JAVA有两个开源程序是必看的,请问是哪两个。在那里下载?
- 错在那里???
- 如何将自己开发的类打包(生成.jar文件)
- 抽象类 匿名类
- 【算法高手】字符串数组的处理
如果想按年龄来排列,可以
public int compare(Object o1,Object o2){
Student s1=(Student)o1;
Student s2=(Student)o2;
if(s1.getAge()==s2.getAge()){ //年龄相同
return s1.getName().compareTo(s2.getName()); //则按姓名比较
}
return s1.getAge()>s2.getAge()?1:-1;
}
而是想让大家帮我解释一个事情:两个对象明显不同,为什么JDK中的TreeSet还是认为是一个对象???难道TreeSet的作者就没有考虑过这个问题吗??难道年龄一样大导致compare的结果为0,就直接调用setValue方法了???就不考虑是否是同一个对象??我的解决方法是只能自己在compare中考虑equals。疑惑的是TreeSet应该将equals的判断嵌入在他的put方法中的。
TreeSet中的add方法:
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
TreeMap中的put方法:
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key); if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);//这个地方是罪槐祸首
} while (t != null);
}
else {
解决方法除了你改写已有的compare方法,你可以重新实现一个Comparator,然后把这个Comparator作为构造参数传递给TreeSet
我觉得你的Student直接Comparable接口,然后compareTo()方法按照API的约定实现,这样比较好。
其他地方如果需要不同的排序算法,那么你在重新实现就是。我觉得String类就是一个比较好的例子,本身实现了Comparable接口,而且同时实现了一个CaseInsensitiveComparator提供compareToIgnoreCase()方法。
TreeSet调用的是compareTo或compare方法来比较元素,然后用比较结果来排序,这样,排在同一个位置的就被看成是同一个元素,否则就不因该排在同一个位置,所以并不是单纯地用equals和hashCode来判断是不是同一个元素。TreeSet底层就是这么实现的,这也正是特殊的地方,所以需要特别注意。在javadoc里有明确地说明了这一点
一下是javadoc里的说明,注意红色部分public class TreeSet<E>extends AbstractSet<E>implements NavigableSet<E>, Cloneable, Serializable基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。 此实现为基本操作(add、remove 和 contains)提供受保证的 log(n) 时间开销。 注意,如果要正确实现 Set 接口,则 set 维护的顺序(无论是否提供了显式比较器)必须与 equals 一致。(关于与 equals 一致 的精确定义,请参阅 Comparable 或 Comparator。)这是因为 Set 接口是按照 equals 操作定义的,但 TreeSet 实例使用它的 compareTo(或 compare)方法对所有元素进行比较,因此从 set 的观点来看,此方法认为相等的两个元素就是相等的。即使 set 的顺序与 equals 不一致,其行为也是 定义良好的;它只是违背了 Set 接口的常规协定。 注意,此实现不是同步的。如果多个线程同时访问一个 TreeSet,而其中至少一个线程修改了该 set,那么它必须 外部同步。这一般是通过对自然封装该 set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSortedSet 方法来“包装”该 set。此操作最好在创建时进行,以防止对 set 的意外非同步访问: SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));此类的 iterator 方法返回的迭代器是快速失败 的:在创建迭代器之后,如果从结构上对 set 进行修改,除非通过迭代器自身的 remove 方法,否则在其他任何时间以任何方式进行修改都将导致迭代器抛出 ConcurrentModificationException。因此,对于并发的修改,迭代器很快就完全失败,而不会冒着在将来不确定的时间发生不确定行为的风险。 注意,迭代器的快速失败行为无法得到保证,一般来说,存在不同步的并发修改时,不可能作出任何肯定的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的做法是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测 bug。 此类是 Java Collections Framework 的成员。
例如:两个Person,他们的身份证号、地址、身高等都不同。唯独只有年龄相同。此时,compareTo内部实现时出现了:if(this.age == person.age ){return 0 ;} --> 那么当两个完全不同的person,只要它们的年龄相同,则认为两个person是同一个person,所以第二个person不会add成功。why?不符合常理啊。