sortedset.subset返回size==0子集

f5emj3cl  于 2021-06-30  发布在  Java
关注(0)|答案(2)|浏览(302)

别紧张,这是我第一次在这个级别上使用比较器。

@SuppressWarnings({ "rawtypes", "unchecked" })
public T getObjectFromExample(T object)
    {
        if (!sorted)
            throw new IllegalStateException();
        SortedSet<T> subset = setReference.subSet(object,object);
        if (subset.size() == 0)
        {
            clsMainProgram.DebugMessage("Returned null for "+object.getClass().getName());
            return null;
        }
        return subset.first();
    }

…是我在树集上使用的方法调用,声明如下。

setReference =  Collections.synchronizedSortedSet(new TreeSet<T>(comparator));

这是比较仪

public class clsComparator implements Serializable, Comparator<infIDClass> {
    private static final long serialVersionUID = -4212404170394031421L;
    @Override
    public int compare(infIDClass o1, infIDClass o2) {
        // TODO Auto-generated method stub
                int z1 = (int)o1.GetID();
                int z2 = (int)o2.GetID();;
                if(z1 > z2)
                    return 1;
                return z2 <= z1 ? 0 : -1;
    }
}

infidclass就是这样:

public interface infIDClass {
    public int GetID();
    public int SetID(int newID);
}

我传递给另一个具有相同id的对象的构造如下:

//USED ONLY FOR COMPARISONS
private Building(int bID) {
    this.ID = bID;
}

传递的对象只是一个带有int id的空模板,比较器将不同的项比较到集合中的方法是将id整数从低到高排序。这背后的想法是获得一种快速有效的方法,从set引用中获取具有id的对象,而不必遍历整个对象。
出于某种原因,每当我运行getobjectfromexample时,有一半的时间它都会返回null值,而当使用tailset和hedset时,它似乎会做同样的事情。我不完全清楚它为什么要这样做,代码看起来对我来说是正确的。
我不知道为什么它会这样做,除了一些模板铸造时,发送给比较,但我不确定。

hsvhsicv

hsvhsicv1#

我想问题来了 SortedSet<T> subset = setReference.subSet(object,object); 根据api subSet 提供第一个参数(包含)到第二个参数(独占)之间的元素。所以这个电话 setReference.subSet(object,object) 将始终返回空集

wixjitnu

wixjitnu2#

从你的代码我可以理解你有一个 SortedSet (这只是一个接口)由 TreeSet (sortedset接口的实现)。我还假设您的“dummysearchobject”对象/类用于搜索集合中的匹配元素 Building “也在实施 infIDClass 接口-否则您可能已经得到一个编译错误。
通过在树集中指定比较器,可以确保元素在树集中按正确的顺序排序。事实上,树集正在执行基于 compare(To) 方法,因此 Comparator 如javadocs中所述。
这就意味着违反合同 hashcode 以及 equals 方法不是这里的问题,我认为首先是出了问题(坚持这个合同是非常重要的,如果不这样做可能会导致意外和难以发现的错误-所以你可能还想检查这个)。
在子集方法的javadoc的基础上:
... 返回此集合中元素范围从fromement,inclusive到toelement,exclusive的部分的视图(如果fromelement和toelement相等,则返回的集为空。)。。。
这意味着您的代码运行良好,符合文档要求。如果要检索非空子集,必须指定fromement和fromement+1。这在不动产中是很难做到的,因为我们不知道fromelement+1是什么。那么,如何从集合中找到/获取要查找的元素呢?
不幸的是,set实现没有指定任何“get”方法来直接基于索引访问任何元素。所以要从集合中找到你的元素,你可以
切换到支持这种索引访问的实现(比如hashmap或linkedhashmap),但是您的元素将不再被排序。也要记得满足于 hashcode 以及 equals 合同在这种情况下!)
您可以使用迭代器(如这里所解释的)或流之类的方法通过迭代集合来查找元素
编辑:备注:还执行 SortedSet.subSet 将遍历整个列表以查找匹配的元素。
使用流可以这样实现:

yourSortedSet.stream().filter((elementFromSet) -> comparator.compare(dummySearchObject, elementFromSet) == 0).findFirst();

注意:流方法使用 comparator.compare 方法(这是传递给treeset构造函数的同一个比较器实现)。正在使用比较器实现,因为 hashcode 以及 equals 方法没有在您的示例中实现(至少从上面的代码片段中看不出这一点)。如果您正确地实现了它们,那么equals方法可以用来对对象进行“简单”的比较。
.findfirst()方法将返回可继续使用的可选对象的示例。例如(根据你上面的例子):

if (!Optional.isPresent())
    {
        clsMainProgram.DebugMessage("Returned null for "+object.getClass().getName());
        return null;
    }

return Optional.get();

非常重要:比较器的实现不是错误的,也不是导致问题的原因,但它根本不是最佳的。它会阻止你的树集正确地分配和排序它的元素,让它变得非常低效。
编辑:事实上,它使您的比较器实现正确,因为它使用-1、0和1的完整范围作为返回值。但是很难阅读/理解,因此仍然建议使用下面的实现。
因此,使用比较器实现如下:

Comparator.comparingInt(infIDClass::GetID);

正如thomas kl所建议的ä在他的回答中,格格是一条路要走。另外,您的模型类非常简单和小如果您的实际用途更复杂,您可以考虑添加另一个属性,以便在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
    }
}

相关问题