簡體   English   中英

排序集的最快方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM