Mentre la risposta con il voto più alto è la risposta assolutamente migliore rispetto a Java 8, è allo stesso tempo assolutamente peggiore in termini di prestazioni. Se vuoi davvero un'applicazione cattiva a basse prestazioni, vai avanti e usala. Il semplice requisito di estrarre un insieme univoco di nomi di persona deve essere raggiunto con un semplice "Per-ciascuno" e un "insieme". Le cose peggiorano ulteriormente se l'elenco ha dimensioni superiori a 10.
Considera di avere una raccolta di 20 oggetti, in questo modo:
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"));
Dove l'oggetto SimpleEvent
appare così:
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;
}
}
E per testare, hai codice JMH come questo, (Nota, sto usando lo stesso distinto Predicato di KeyKey menzionato nella risposta accettata):
@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();
}
Quindi otterrai risultati di benchmark come questo:
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
E come puoi vedere, un semplice For-Each ha una resa 3 volte migliore e un punteggio di errore inferiore rispetto a Java 8 Stream.
Maggiore è la produttività, migliori le prestazioni
Function<? super T, ?>
, noFunction<? super T, Object>
. Inoltre, va notato che per il flusso parallelo ordinato questa soluzione non garantisce quale oggetto verrà estratto (a differenza del normaledistinct()
). Anche per i flussi sequenziali c'è un sovraccarico aggiuntivo sull'uso di CHM (che è assente nella soluzione @nosid). Infine, questa soluzione viola il contratto difilter
metodo che il predicato deve essere apolide come indicato in JavaDoc. Tuttavia votato.