Während die am höchsten bewertete Antwort die absolut beste Antwort für Java 8 ist, ist sie gleichzeitig absolut schlecht in Bezug auf die Leistung. Wenn Sie wirklich eine schlechte Anwendung mit geringer Leistung wünschen, verwenden Sie sie. Das einfache Erfordernis, einen eindeutigen Satz von Personennamen zu extrahieren, wird durch bloßes "Für jeden" und einen "Satz" erreicht. Es wird noch schlimmer, wenn die Liste über 10 liegt.
Angenommen, Sie haben eine Sammlung von 20 Objekten wie folgt:
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"));
Wo Ihr Objekt so SimpleEvent
aussieht:
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;
}
}
Und zum Testen haben Sie einen JMH- Code wie diesen (Bitte beachten Sie, dass ich dasselbe eindeutige ByKey-Prädikat verwende, das in der akzeptierten Antwort erwähnt wird):
@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();
}
Dann haben Sie folgende Benchmark- Ergebnisse:
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
Und wie Sie sehen können, ist ein einfacher For-Each dreimal besser im Durchsatz und weniger fehlerhaft als Java 8 Stream.
Je höher der Durchsatz, desto besser die Leistung
Function<? super T, ?>
nicht seinFunction<? super T, Object>
. Es sollte auch beachtet werden, dass diese Lösung für geordnete parallele Streams nicht garantiert, welches Objekt extrahiert wird (im Gegensatz zu normaldistinct()
). Auch für sequentielle Streams entsteht ein zusätzlicher Aufwand für die Verwendung von CHM (der in der @ nosid-Lösung nicht vorhanden ist). Schließlich verstößt diese Lösung gegen denfilter
Methodenvertrag, dessen Prädikat zustandslos sein muss, wie in JavaDoc angegeben. Trotzdem positiv bewertet.