我创建了一个这样的Student类:
public class Student implements Comparable<Student> {
private String firstName;
private String lastName;
public Student(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
// Getters & Setters follow here...
@Override
public int compareTo(Student student) {
int hash = this.firstName.compareTo(student.firstName);
return hash;
}
@Override
public String toString() {
return "Student [firstName=" + firstName + ", lastName=" + lastName
+ "]";
}
}
这是我的测试类,我只是在我的TreeSet中添加元素:
public class SortedSetExample1 {
public static void main(String[] args) {
SortedSet<Student> set = new TreeSet<Student>();
set.add(new Student("A1","A2"));
set.add(new Student("B1","B2"));
set.add(new Student("A1","B2"));
set.add(new Student("A2","B2"));
System.out.println(set);
}
}
根据我的程序,输出为:
[Student [firstName=A1, lastName=A2], Student [firstName=A2, lastName=B2], Student [firstName=B1, lastName=B2]]
在我的测试课程中,我将Student
个对象添加到TreeSet
,而且我还没有覆盖hashCode
&amp; equals
方法。所以我期待TreeSet
将保存所有4个对象,但我也可以看到它包含3个对象。您能否解释为什么new Student("A1","B2")
不属于我的TreeSet
?
此外,根据此处的Java docs for TreeSet,它说:
如果指定的元素尚不存在,则将其添加到此集合中。 更正式地说,如果集合,则将指定的元素e添加到此集合中 不包含元素e2(e == null?e2 == null:e.equals(e2))。 如果此集合已包含该元素,则该调用将离开该集合 不变并返回false。
由于我没有覆盖equals
方法,为什么该集合没有所有四个元素?
答案 0 :(得分:10)
正如java.util.TreeSet所说:
TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,这个方法认为相等的两个元素相等
感谢@Jon Skeet。
答案 1 :(得分:1)
这是因为TreeSet
使用compareTo
(或Comparator.compare
)来测试两个元素是否相等。这就是文档所说的内容。
请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器)必须与equals一致。 (有关与equals一致的精确定义,请参阅Comparable或Comparator。)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,通过这种方法被认为相等的元素是相等的。集合的行为即使其排序与equals不一致也是明确定义的;它只是没有遵守Set接口的一般合同。
答案 2 :(得分:1)
由于您只比较了compareTo方法中的第一个名称,因此需要
@Override
public int compareTo(Student student) {
int comp = this.firstName.compareTo(student.firstName);
if(comp==0) return this.lastName.compareTo(student.lastName);
return comp;
}
当compareTo返回0时,treeSet假定它是重复的。
答案 3 :(得分:0)
尽管问题已经很老了,但这是了解大多数人在实施过程中忽略哪些问题的非常重要的一点。
TreeSet
不会将新元素与Set
中所有现有元素进行比较。它使用二进制搜索技术。因此,如果您的输入元素等于现有元素(根据compareTo
合同),并且位于tree
的左侧,则您的compareTo
方法的实现方式是强制您的新元素位于tree
的右侧,即使您的TreeSet
中已经存在新元素(根据compareTo
合同),您的Item
也不会拒绝。让我们看下面的简单示例。
我需要对key
个具有priority
和package com.manish;
import java.util.TreeSet;
public class Main {
static class Item implements Comparable<Item> {
private long key;
private int priority;
public Item(long key, int priority) {
super();
this.key = key;
this.priority = priority;
}
/*
* Items should be treated equal if Keys are equal.
* Higher priority item should be treated as greater item.
* If priorities are same, lower key value item should be
* treated as greater item.
*/
@Override
public int compareTo(Item o) {
if (this.key == o.key) {
return 0;
}
if (this.priority != o.priority) {
return this.priority - o.priority;
} else {
return this.key < o.key ? 1 : -1;
}
}
@Override
public String toString() {
return "Item [key=" + key + ", priority=" + priority + "]";
}
}
public static void main(String[] args) {
TreeSet<Item> set = new TreeSet<>();
set.add(new Item(2, 1));
set.add(new Item(4, 3));
set.add(new Item(3, 1)); //line 1
set.add(new Item(3, 2)); //line 2. Same item as Item(3,1)
while (!set.isEmpty())
System.out.println(set.pollFirst());
}
}
属性的属性进行排序。
Item [key=3, priority=1]
Item [key=2, priority=1]
Item [key=3, priority=2]
Item [key=4, priority=3]
输出:
line 1
但是,如果交换line 2
和Item [key=2, priority=1]
Item [key=3, priority=2]
Item [key=4, priority=3]
代码,则输出将更改如下。
Dim SUMrow As Long
Dim Arg1 As Variant
Dim Arg2 As Range
Dim Arg3 As Range
Dim sumvalue As String
Dim ws As Worksheet
For SUMrow = 2 To 99999
If (Workbooks("ExpenseDataMcframe.xlsm").Worksheets("ImportData2").Range("b" & SUMrow) = "") Then Exit For
Set Arg1 = Workbooks("ExpenseDataMcframe.xlsm").Worksheets("ImportData2").Range("L:L")
Set Arg2 = Workbooks("ExpenseDataMcframe.xlsm").Worksheets("ImportData2").Range("B:B")
Set Arg3 = Workbooks("ExpenseDataMcframe.xlsm").Worksheets("ImportData2").Range("C:C")
'sumvalue = WorksheetFunction.SUMIFS(L:L,B:B,B:B,C:C,C:C)
' sumvalue = Application.WorksheetFunction.SumIfs(Arg1, Arg2, Arg2, Arg3, Arg3)
Set ws = Workbooks("ExpenseDataMcframe.xlsm").Worksheets("ImportData2")
'apply the Excel SUMIF function
sumvalue = WorksheetFunction.SumIfs(ws.Range("L:L"), ws.Range("B:B"), ws.Range("B:B"), ws.Range("C:C"), ws.Range("C:C"))
Workbooks("ExpenseDataMcframe.xlsm").Worksheets("ImportData2").Range("N" & SUMrow).Value = sumvalue
'End If
'End If
Next
答案 4 :(得分:-1)
嗯,你的树形键值是&#34; A1&#34;,&#34; B1&#34;,&#34; A1&#34;,&#34; A2&#34;。即使你没有覆盖equals和hashcode仍然是&#34; A1&#34;的默认哈希码。将是相同的,因此树集会将此密钥视为重复密钥,因此您将无法输入&#34; A1&#34;,&#34; B2&#34;