我可以从您的代码中了解到,您有一个 SortedSet(这只是一个接口),它是由一个 TreeSet(SortedSet 接口的实现)实现的。我还假设您用于搜索“Building”集合中匹配元素的“dummySearchObject”对象/类也实现了infIDClass 接口 - 否则您可能已经遇到编译错误。
通过在 TreeSet 中指定比较器,可以确保您的元素在 TreeSet 中以正确的顺序排序。事实上,TreeSet 正在执行基于compare(To) 方法的所有操作,因此在Comparator 上执行所有操作,如JavaDocs 中所述。
这意味着违反hashcode 和equals 方法的合同不是这里的问题,我认为首先出了问题(坚持这个合同非常重要,如果不这样做会导致意外和难以发现错误 - 所以你可能还想检查一下)。
进一步来自JavaDoc of subSet method:
... 返回此集合的一部分的视图,其元素范围为
fromElement,包含,toElement,排除。 (如果 fromElement 和
toElement 相等,返回的集合为空。) ...
这意味着您的代码运行良好,并且符合文档。如果要检索非空子集,则必须指定 fromElement 和 fromElement + 1。这实际上很难做到,因为我们不知道 fromElement + 1 将是什么。那么如何从 Set 中找到/获取要查找的元素?
不幸的是,Set 实现没有指定任何“get”方法来直接访问基于它们的索引的任何元素。因此,要从 Set 中找到您的元素,您可以
- 切换到支持此类索引访问的实现(如 HashMap 或 LinkedHashMap - 但您的元素将不再被排序。在这种情况下还要记住满足
hashcode 和 equals 合同!)
- 您可以使用迭代器 (as explained here) 或流等通过遍历 Set 来查找元素
编辑:备注:SortedSet.subSet 的实现也会遍历整个列表以找到匹配的元素。
使用流可以这样实现:
yourSortedSet.stream().filter((elementFromSet) -> comparator.compare(dummySearchObject, elementFromSet) == 0).findFirst();
注意:流方法使用comparator.compare 方法(这与传递给 TreeSet 构造函数的 Comparator 实现相同)。正在使用比较器实现,因为您的示例中没有实现 hashcode 和 equals 方法(至少从上面的 sn-p 中不明显)。如果你正确地实现它们,equals方法可以用来做对象的“简单”比较。
.findFirst() 方法将返回一个 Optional 的实例,您可以继续使用。例如(根据你上面的例子):
if (!Optional.isPresent())
{
clsMainProgram.DebugMessage("Returned null for "+object.getClass().getName());
return null;
}
return Optional.get();
非常重要:
您的 Comparator 的实现没有错误或导致问题,但它根本不是最优的。它会阻止您的 TreeSet 正确分配和排序它的元素,使其变得非常低效。
编辑:实际上它使您的比较器实现正确,因为它使用 -1、0 和 1 的全部范围作为返回值。虽然它很难阅读/理解,所以仍然建议使用下面的实现。
因此使用 Comparator 实现,如:
Comparator.comparingInt(infIDClass::GetID);
正如 Thomas Kläger 在他的回答中所建议的那样,这是要走的路。此外,如果您的实际目的更复杂,您的模型类也非常简单和小,您可以考虑在 TreeSet 中添加其他属性以更有效地存储/排序(当然,前提是它也适合您的业务用例。可比性/唯一性您的对象应该主要由您的业务领域驱动)。
最后但并非最不重要的是,您可以从以下代码中找到完整的编码示例:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.SortedSet;
import java.util.TreeSet;
public class Driver {
static List<Wrapper> dummyData = initializeDummyData();
// Used to create some dummy data
private static List<Wrapper> initializeDummyData() {
List<Wrapper> dummyData = new ArrayList<>(
Arrays.asList(new MyClass(1), new MyClass(2), new MyClass(3), new MyClass(4), new MyClass(5)));
return dummyData;
}
public static void main(String[] args) {
MyComparator comparator = new MyComparator();
// Creating the SortedSet with a Comparator and filling it with dummy data
SortedSet<Wrapper> theSortedSet = new TreeSet<>(comparator);
theSortedSet.addAll(dummyData);
Wrapper dummySearchObject = new MyClass(2);
Wrapper dummySearchObject2 = new MyClass(3);
// Calling subSet and fromElement and toElement are same
System.out.println(theSortedSet.subSet(dummySearchObject, dummySearchObject));
// Will print empty result: []
// Calling subSet and toElement is fromElement + 1
System.out.println(theSortedSet.subSet(dummySearchObject, dummySearchObject2));
// Will print: [My id is: 2]
// Example with stream and Optional
Optional<Wrapper> retrievedElement = theSortedSet.stream()
.filter((elementFromSet) -> comparator.compare(dummySearchObject, elementFromSet) == 0).findFirst();
if(retrievedElement.isPresent()) {
// Element is there, do something with it
System.out.println("Yes");
} else {
// Element is not there
System.out.println("No");
}
}
}
interface Wrapper { // Equivalent to infIDClass interface
public int getId();
}
class MyClass implements Wrapper { // Implementation of infIDClass => Equivalent to Building?
private int id;
MyClass(int id) {
this.id = id;
}
@Override
public int getId() {
return id;
}
@Override
public String toString() {
return "My id is: " + id;
}
}
class MyComparator implements Serializable, Comparator<Wrapper> { // The Comparator implementation
private static final long serialVersionUID = -4212404170394031421L;
@Override
public int compare(Wrapper o1, Wrapper o2) {
int z1 = (int) o1.getId();
int z2 = (int) o2.getId();
if (z1 > z2)
return 1;
return z2 <= z1 ? 0 : -1; // => This should be adjusted (e.g. "Comparator.comparingInt(infIDClass::GetID);") to have an efficient storing/ sorting in the TreeSet
}
}