Sementara jawaban tertinggi yang dipilih adalah jawaban terbaik untuk Java 8, namun pada saat yang sama benar-benar terburuk dalam hal kinerja. Jika Anda benar-benar menginginkan aplikasi berkinerja rendah yang buruk, silakan gunakan. Persyaratan sederhana untuk mengekstraksi seperangkat Nama Person yang unik harus dicapai hanya dengan "Untuk Setiap" dan "Set". Hal-hal menjadi lebih buruk jika daftar di atas ukuran 10.
Pertimbangkan Anda memiliki koleksi 20 Objek, seperti ini:
public static final List<SimpleEvent> testList = Arrays.asList(
new SimpleEvent("Tom"), new SimpleEvent("Dick"),new SimpleEvent("Harry"),new SimpleEvent("Tom"),
new SimpleEvent("Dick"),new SimpleEvent("Huckle"),new SimpleEvent("Berry"),new SimpleEvent("Tom"),
new SimpleEvent("Dick"),new SimpleEvent("Moses"),new SimpleEvent("Chiku"),new SimpleEvent("Cherry"),
new SimpleEvent("Roses"),new SimpleEvent("Moses"),new SimpleEvent("Chiku"),new SimpleEvent("gotya"),
new SimpleEvent("Gotye"),new SimpleEvent("Nibble"),new SimpleEvent("Berry"),new SimpleEvent("Jibble"));
Di mana Anda keberatan SimpleEvent
terlihat seperti ini:
public class SimpleEvent {
private String name;
private String type;
public SimpleEvent(String name) {
this.name = name;
this.type = "type_"+name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Dan untuk menguji, Anda memiliki JMH kode seperti ini, (Harap dicatat, im menggunakan yang sama distinctByKey Predikat disebutkan dalam jawaban diterima):
@Benchmark
@OutputTimeUnit(TimeUnit.SECONDS)
public void aStreamBasedUniqueSet(Blackhole blackhole) throws Exception{
Set<String> uniqueNames = testList
.stream()
.filter(distinctByKey(SimpleEvent::getName))
.map(SimpleEvent::getName)
.collect(Collectors.toSet());
blackhole.consume(uniqueNames);
}
@Benchmark
@OutputTimeUnit(TimeUnit.SECONDS)
public void aForEachBasedUniqueSet(Blackhole blackhole) throws Exception{
Set<String> uniqueNames = new HashSet<>();
for (SimpleEvent event : testList) {
uniqueNames.add(event.getName());
}
blackhole.consume(uniqueNames);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(MyBenchmark.class.getSimpleName())
.forks(1)
.mode(Mode.Throughput)
.warmupBatchSize(3)
.warmupIterations(3)
.measurementIterations(3)
.build();
new Runner(opt).run();
}
Maka Anda akan mendapatkan hasil Benchmark seperti ini:
Benchmark Mode Samples Score Score error Units
c.s.MyBenchmark.aForEachBasedUniqueSet thrpt 3 2635199.952 1663320.718 ops/s
c.s.MyBenchmark.aStreamBasedUniqueSet thrpt 3 729134.695 895825.697 ops/s
Dan seperti yang Anda lihat, For-Each sederhana adalah 3 kali lebih baik dalam throughput dan skor kesalahan kurang dibandingkan dengan Java 8 Stream.
Semakin tinggi throughput, semakin baik kinerjanya
Function<? super T, ?>
, bukanFunction<? super T, Object>
. Juga harus dicatat bahwa untuk aliran paralel yang dipesan solusi ini tidak menjamin objek mana yang akan diekstraksi (tidak seperti normaldistinct()
). Juga untuk aliran berurutan ada overhead tambahan dalam menggunakan CHM (yang tidak ada dalam solusi @nosid). Akhirnya solusi ini melanggar kontrakfilter
metode yang predikatnya harus stateless seperti yang dinyatakan dalam JavaDoc. Namun demikian, diputuskan.