[英]Fastest way to sort a set
我正在使用現有數據庫中的Hibernate替換工作中使用的應用程序。 我無法修改數據庫,因為它與其他進程一起使用。 當Hibernate從db中提取主對象時,子對象將被放入無序集合中。 我以前從未真正處理過集合或排序集。
我需要為每一組顯示最后一個(按時間順序排列)的孩子。 沒有為子對象存儲日期,但由於db中的id字段是AUTO_INCREMENT,我可以用id對它們進行排序來代替日期。
關於使用現有系統的一個抱怨是,它真的非常非常慢。 我想用新的應用程序顯示速度的明顯提高。
給定一個具有0到n“家庭地址”的Person對象(變量名“off”),我正在使用:
Set addressSet = off.getAddresses();
List<Address> addressList = new ArrayList<>();
Iterator i = addressSet.iterator();
while(i.hasNext()){
addressList.add((Address) i.next());
}
Collections.sort(addressList, new AddressComparator());
Address a = null;
if(addressList.size()>0){
a = addressList.get(addressList.size()-1);
}else{
a = new Address(); //creates new Address object with empty strings
//for fields
}
我的簡單比較器是:
public int compare(Address t, Address t1) {
return t.getId().compareTo(t1.getId());
}
我的問題:通過Java或Hibernate,有沒有更快的方法來對集合進行排序?
從我的角度來看,你根本不需要排序。 采用
Collections.max()
要么
Collections.min()
提供自定義比較器以查找所需的地址。 與O(nlog(n))排序時間相比,這在最壞的情況下具有O(n)運行時間,因為您不排序並且僅迭代您的集合一次。 積極的部分還在於您不需要將Set
轉換為List
因為max和min方法適用於任何Collection
實例。
另一個優點(至少對我來說)是Collections
實用程序是java運行時的一部分,因此您不需要添加任何第三方庫。
您可以在沒有臨時列表的情況下執
TreeSet sortedSet = Sets.newTreeSet(new AddressComparator());
sortedSet.addAll(off.getAddresses());
return sortedSet.first(); // or sortedSet.last() see what is suitable for you
套裝細節。
UPD。
還請參閱番石榴訂購解決方案 。 它將允許您獲得最大元素而無需臨時收集。
Ordering<Adress> ordering = Ordering.from(new AddressComparator());
return ordering.max(off.getAddresses());
我不確定是否有多個集合,但從代碼中看起來你只是獲得具有最高id的Address
。 這可以通過以下sql實現,這不需要排序。
select * from table where id = (select max(id) from table);
您可以使用@OrderBy屬性在JPA / Hibernate中對數據庫級別進行排序,其中排序位於非嵌套屬性上。 所以在你的情況下你可以做到這一點。
例如
@OneToMany
@OrderBy("id");
public Set<Address> addresses;
和Hibernate將確保集合在一個有序集合中。
如果sort字段恰好位於嵌套屬性上(在你的情況下不是這樣),例如person.address.town.population,那么你仍然可以使用Hibernate處理排序使用Hibernate特定(非JPA)@Sort注釋這將確保如上所述的排序集,但將使用內存排序而不是DB order by子句進行排序。
@OneToMany
@Sort(//natural or specify a comparator);
public Set<Address> addresses;
這當然不會讓你獲得最新的地址。 如果您不想將映射從Set更改為允許您獲取最新的索引,那么您也可以通過各種方式在數據庫層中執行此操作,例如,通過創建基於每個最大地址ID的視圖人。
@Entity
@Table(name = "vw_most_recent_addresses"
public class MostRecentAddress extends Address{
}
public class Person{
@OneToMany
@OrderBy("id");
public Set<Address> addresses;
@OneToOne
public MostRecentAddress mostRecentAddress;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.