我的问题的基础是在Java中给出一个List对象,什么是返回唯一数据集合的最快方法?
更具体的版本是,我有一个2d ArrayList(想象它就像一个表),我想循环遍历给定的列索引并返回唯一数据。
这是我当前的设置:
public Set<Object> getDistinctColumnData( int colIndex ) {
//dataByIndex = List<List<Object>>
Set<Object> colDistinctData = new HashSet<Object>( dataByIndex.size() + 1, 1f ) ;
for( List<Object> row : dataByIndex ) {
colDistinctData.add( row.get( colIndex ) ) ;
}
return colDistinctData ;
}
当我将初始容量设置为非独特集合的大小加上1并且负载因子为1时,我获得了小的性能提升(我的想法是它赢得了不需要增长直到达到100%,即使原始集合已经100%不同(或者我错了吗?),也不会发生这种情况。)
有更快的方法吗?
答案 0 :(得分:0)
我认为如果你只有两个独特的收藏品会更快。维护dataByIndex列表,还维护一个dataSet Collection(Set)。当您插入dataByIndex列表时,也会将其放入您的dataSet Set中。然后只需在需要的地方使用您的dataSet。该集合将保持作为集合的本质的唯一性。
答案 1 :(得分:0)
我认为在为您指定的值设置容量和加载因子方面没有多大意义。您使用什么散列函数?可能会降级到链表吗?
答案 2 :(得分:0)
如果你更多地增加HashSet的初始容量,你可能会进一步提升性能(平均)。这是因为列表中对象的哈希值的分布可能更容易发生冲突。
例如,给定以下列表,除了第一次插入之外的所有内容都将导致冲突,尽管没有重复值。 (整数的Java哈希函数是整数本身的值,HashSet在发生冲突时使用开放寻址和线性探测)。
[0,10,1,2,3,4,5,6,7]
或更糟糕的是,因为每个插入都必须在插入之前检查每个非空闲空间。
[0, 5, 25, 125]
在最后一个例子中,0被放入索引0. 5最初进入索引0,因为5%大小(即5)等于0,所以然后转到索引1. 125将转到索引0,但是0到达0索引0,5在索引1处,25处在索引2处。这意味着在三次检查之后125最终可以在索引3处插入。
如果增加初始容量,则会降低碰撞的概率(平均),并且如果发生碰撞(也平均),则减少所需的检查次数。默认情况下,java使用0.75的加载因子作为性能和内存使用之间的良好平衡。因此除以负载系数0.75,加1应该给你一个良好的初始容量。