简体   繁体   English

有效地比较Java中的两个对象列表

[英]Efficiently comparing two lists of objects in Java

I'm currently looking through two very large lists of Peak Objects, by overriding the equals method and looping through the two lists, comparing every peak to every other peak. 我目前正在查看两个非常大的Peak Objects列表,通过覆盖equals方法并循环遍历两个列表,将每个峰值与每个其他峰值进行比较。 Is there a more efficient way of doing this? 有更有效的方法吗? My lists can be ~10,000 elements, which means up to 10000 * 10000 comparisons. 我的列表可以是~10,000个元素,这意味着最多10000 * 10000个比较。

The code for my peak object: 我的峰值对象的代码:

public class Peak extends Object{

private final SimpleIntegerProperty peakStart;
private final SimpleIntegerProperty peakEnd;
private final SimpleIntegerProperty peakMaxima;
private final SimpleIntegerProperty peakHeight;
private final SimpleIntegerProperty peakWidth;
private final SimpleStringProperty rname;

public Peak(int peakStart, int peakEnd, int peakMaxima, int peakHeight, String rname) {
    this.peakStart = new SimpleIntegerProperty(peakStart);
    this.peakEnd = new SimpleIntegerProperty(peakEnd);
    this.peakMaxima = new SimpleIntegerProperty(peakMaxima);
    this.peakHeight = new SimpleIntegerProperty(peakHeight);
    this.peakWidth = new SimpleIntegerProperty(peakEnd - peakStart);
    this.rname = new SimpleStringProperty(rname);
}

public String getRname() {
    return rname.get();
}

public SimpleStringProperty rnameProperty() {
    return rname;
}

public int getPeakWidth() {
    return peakWidth.get();
}

public int getPeakHeight() {
    return peakHeight.get();
}

public int getPeakStart() {
    return peakStart.get();
}

public int getPeakEnd() {
    return peakEnd.get();
}

public int getPeakMaxima() {
    return peakMaxima.get();
}

@Override
public String toString() {
    return "Peak{" +
            "peakStart= " + peakStart.get() +
            ", peakEnd= " + peakEnd.get() +
            ", peakHeight= " + peakHeight.get() +
            ", rname= " + rname.get() +
            '}';
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Peak peak = (Peak) o;

    if (!peakMaxima.equals(peak.peakMaxima)) return false;
    return rname.equals(peak.rname);
}

@Override
public int hashCode() {
    int result = peakMaxima.hashCode();
    result = 31 * result + rname.hashCode();
    return result;
}
}

And my loop for comparing the objects is here. 我在这里比较对象的循环。

 List<Peak> interestingPeaks = new ArrayList<>();

            if(peakListOne != null && peakListTwo != null){
                for(Peak peak : peakListOne){
                    for(Peak peak2 : peakListTwo){
                        if(peak.equals(peak2)){ //number one, check the rnames match
                            if((peak2.getPeakHeight() / peak.getPeakHeight() >= 9) || (peak.getPeakHeight() / peak2.getPeakHeight() >= 9)){
                                    interestingPeaks.add(peak);
                            }
                        }
                    }
                }
            }

            return interestingPeaks;

The code is basically matching the position of the maxima, and the rname , which is just a String. 代码基本上匹配最大值的位置和rname ,它只是一个String。 Then appending the peak to the interestingPeaks list if the height of one is a factor of 9x larger than the other. 然后将峰值附加到interestingPeaks列表中,如果一个高度比另一个高9倍。

Appreciate that if the two lists were sorted by maxima and name, you could simply make a single linear pass down both lists, and compare items side by side. 请注意,如果两个列表按最大值和名称排序,您可以简单地在两个列表中进行单个线性传递,并且并排比较项目。 If the two lists were in fact completely equal, then you would never find a pair from the two lists which were not equal. 如果两个列表实际上完全相同,那么你永远不会从两个不相等的列表中找到一对。

List<Peak> p1;
List<Peak> p2;

p1.sort((p1, p2) -> {
    int comp = Integer.compare(p1.getPeakMaxima(), p2.getPeakMaxima());
    return comp != 0 ? comp : p1.getRname().compareTo(p2.getRname());
});

// and also sort the second list

Now we can just walk down both lists and check for a comparison failure: 现在我们可以走下两个列表并检查比较失败:

for (int i=0; i < p1.size(); ++i) {
    if (!p1.get(i).equals(p2.get(i))) {
        System.out.println("peaks are not equal");
        break;
    }
}

This reduces an O(N^2) operation to one which is O(N*lgN) , which is the penalty for doing both sorts (the final walk down the list is O(N) , and would be negligible with either approach). 这将O(N^2)运算减少到O(N*lgN) ,这是两种排序的惩罚(列表中的最后一步是O(N) ,并且两种方法都可以忽略不计) 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM