没有分析输入很难给出好的答案。不管怎样,我会分享我的结果:
我将Foo
设为一个包含单个long
的容器,并将MyObj
设为单个Foo
的容器。此外,我使所有测试都以将数据复制到普通数组中结束。我还添加了两种方法:
4)。简单数组
@Benchmark
public void simpleArray(Blackhole bh) {
MyObj[] ret = new MyObj[foos.size()];
for (int i=0;i<foos.size();i++)
ret[i] = new MyObj(foos.get(i));
Arrays.sort(ret);
int lastDistinct = 0;
for (int i = 1; i < ret.length; i++) {
if (ret[i].equals(ret[lastDistinct])) {
continue;
}
lastDistinct++;
ret[lastDistinct] = ret[i];
}
MyObj[] ret2 = new MyObj[lastDistinct + 1];
System.arraycopy(ret, 0, ret2, 0, lastDistinct + 1);
bh.consume(ret2);
}
5). 翻转了(2)中distinct
和 order
的顺序:
@Benchmark
public void simpleStream_distinctAfterSort(Blackhole bh) {
List<MyObj> ret = foos.stream().map(MyObj::new)
.sorted().distinct()
.collect(Collectors.toList());
bh.consume(ret.toArray(new MyObj[ret.size()]));
}
测试设置:
public static final int MAX_SIZE = 10_000;
public static final long ELEM_THRESHOLD = MAX_SIZE * 10;
private List<Foo> foos;
@Setup
public void init() throws IOException, IllegalAccessException, InstantiationException {
foos = new ArrayList<>(MAX_SIZE);
for (int i = 0; i < MAX_SIZE; i++) {
foos.add(new Foo(ThreadLocalRandom.current().nextLong(ELEM_THRESHOLD)));
}
}
现在来看不同大小和阈值的结果:
Size=10_000
Threshold=Size*10
Benchmark Mode Cnt Score Error Units
StreamBenchmark5.enhancedLoop_TreeSet thrpt 2 478,978 ops/s
StreamBenchmark5.simpleArray thrpt 2 591,287 ops/s
StreamBenchmark5.simpleStream thrpt 2 407,556 ops/s
StreamBenchmark5.simpleStream_distinctAfterSort thrpt 2 533,091 ops/s
StreamBenchmark5.treeSetStream thrpt 2 492,709 ops/s
Size=10_000
Threshold=Size/10
StreamBenchmark5.enhancedLoop_TreeSet thrpt 2 937,908 ops/s
StreamBenchmark5.simpleArray thrpt 2 593,983 ops/s
StreamBenchmark5.simpleStream thrpt 2 3344,508 ops/s
StreamBenchmark5.simpleStream_distinctAfterSort thrpt 2 560,652 ops/s
StreamBenchmark5.treeSetStream thrpt 2 1000,585 ops/s
Size=500_000
Threshold=Size*10
Benchmark Mode Cnt Score Error Units
StreamBenchmark5.enhancedLoop_TreeSet thrpt 2 1,809 ops/s
StreamBenchmark5.simpleArray thrpt 2 4,009 ops/s
StreamBenchmark5.simpleStream thrpt 2 2,443 ops/s
StreamBenchmark5.simpleStream_distinctAfterSort thrpt 2 4,141 ops/s
StreamBenchmark5.treeSetStream thrpt 2 2,040 ops/s
Size=500_000
Threshold=Size/10
Benchmark Mode Cnt Score Error Units
StreamBenchmark5.enhancedLoop_TreeSet thrpt 2 5,724 ops/s
StreamBenchmark5.simpleArray thrpt 2 4,567 ops/s
StreamBenchmark5.simpleStream thrpt 2 19,001 ops/s
StreamBenchmark5.simpleStream_distinctAfterSort thrpt 2 4,840 ops/s
StreamBenchmark5.treeSetStream thrpt 2 5,407 ops/s
Size=1_000_000
Threshold=Size/100
Benchmark Mode Cnt Score Error Units
StreamBenchmark5.enhancedLoop_TreeSet thrpt 2 4,529 ops/s
StreamBenchmark5.simpleArray thrpt 2 2,402 ops/s
StreamBenchmark5.simpleStream thrpt 2 35,699 ops/s
StreamBenchmark5.simpleStream_distinctAfterSort thrpt 2 2,232 ops/s
StreamBenchmark5.treeSetStream thrpt 2 4,889 ops/s
根据重复的数量不同,可以看到最好的算法也会有所变化。最平衡的方法是TreeSet
(3),然而最快的方法几乎总是简单的流式处理(使用与输入数据对应的order
和distinct
)。
如果您愿意尝试一下,这里是测试源代码。您需要JMH。
Foo
,而它们包含的是MyObj
? - user3707125TreeSet
没有使用int
和float
的构造函数。你确定你不是想说HashSet
吗? - F. Lumnitz.distinct
?你说“...处理不同的...”,那么难道不是所有的都已经是不同的了吗? - Todd Sewellnew TreeSet(size, 1.0f)
是什么意思。 - ZhekaKozlov