排序集的最快方法

时间:2014-05-21 15:22:46

标签: java hibernate sorting

我正在使用现有数据库中的Hibernate替换工作中使用的应用程序。我无法修改数据库,因为它与其他进程一起使用。当Hibernate从db中提取主对象时,子对象将被放入无序集合中。我以前从未真正处理过集合或排序集。

我需要显示每组的最后一个(按时间顺序排列)的孩子。没有为子对象存储日期,但由于数据库中的id字段是AUTO_INCREMENT,我可以用id对它们进行排序来代替日期。

关于现有系统使用的一个抱怨是,它真的非常非常慢。我想用新的应用程序显示速度的明确提高。

给定一个Person对象(变量名称" off"),0到n"家庭地址",我使用:

    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,是否有更快的方法对集合进行排序?

4 个答案:

答案 0 :(得分:3)

从我的角度来看,你根本不需要排序。使用

Collections.max()

Collections.min()

提供自定义比较器以查找所需的地址。与O(nlog(n))排序时间相比,这在最坏的情况下具有O(n)运行时间,因为您不排序并且仅迭代您的集合一次。积极的一面是,您不需要将Set转换为List,因为max和min方法适用于任何Collection实例。

另一个优点(至少对我来说)是Collections实用程序是java运行时的一部分,因此您不需要添加任何第三方库。

答案 1 :(得分:0)

您可以在没有临时列表的情况下执行此操作。

TreeSet sortedSet = Sets.newTreeSet(new AddressComparator());
sortedSet.addAll(off.getAddresses());
return sortedSet.first(); // or sortedSet.last() see what is suitable for you

Sets的详细信息。

UPD。

另请参阅Guava Ordering solution。它将允许您获得最大元素而无需临时收集。

Ordering<Adress> ordering = Ordering.from(new AddressComparator());
return ordering.max(off.getAddresses());

答案 2 :(得分:0)

我不确定是否有多个套装,但从代码来看,您似乎只是获得ID最高的Address。这可以通过以下sql来实现,这不需要排序。

select * from table where id = (select max(id) from table);

答案 3 :(得分:0)

您可以使用@OrderBy属性在JPA / Hibernate中对数据库级别进行排序,其中排序位于非嵌套属性上。所以在你的情况下你可以这样做。

e.g。

@OneToMany
@OrderBy("id");
public Set<Address> addresses;

和Hibernate将确保集合处于有序集合中。

如果排序字段恰好位于嵌套属性上(在您的情况下不是这样),例如person.address.town.population那么你仍然可以让Hibernate使用Hibernate特定的(非JPA)@Sort注释处理排序,它将确保如上所述的排序集,但是将使用内存排序而不是数据库顺序排序子句。

@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;

}