[英]Efficiently comparing two lists of objects in Java
我目前正在查看兩個非常大的Peak
Objects列表,通過覆蓋equals
方法並循環遍歷兩個列表,將每個峰值與每個其他峰值進行比較。 有更有效的方法嗎? 我的列表可以是~10,000個元素,這意味着最多10000 * 10000個比較。
我的峰值對象的代碼:
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;
}
}
我在這里比較對象的循環。
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;
代碼基本上匹配最大值的位置和rname
,它只是一個String。 然后將峰值附加到interestingPeaks
列表中,如果一個高度比另一個高9倍。
請注意,如果兩個列表按最大值和名稱排序,您可以簡單地在兩個列表中進行單個線性傳遞,並且並排比較項目。 如果兩個列表實際上完全相同,那么你永遠不會從兩個不相等的列表中找到一對。
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
現在我們可以走下兩個列表並檢查比較失敗:
for (int i=0; i < p1.size(); ++i) {
if (!p1.get(i).equals(p2.get(i))) {
System.out.println("peaks are not equal");
break;
}
}
這將O(N^2)
運算減少到O(N*lgN)
,這是兩種排序的懲罰(列表中的最后一步是O(N)
,並且兩種方法都可以忽略不計) 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.