Si bien la respuesta más votada es absolutamente la mejor respuesta para Java 8, al mismo tiempo es absolutamente peor en términos de rendimiento. Si realmente desea una aplicación de bajo rendimiento, siga adelante y úsela. El simple requisito de extraer un conjunto único de nombres de personas se logrará mediante un mero "para cada uno" y un "conjunto". Las cosas empeoran aún más si la lista supera el tamaño de 10.
Considere que tiene una colección de 20 objetos, como este:
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"));
Donde objetas se SimpleEvent
ve así:
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;
}
}
Y para probar, tiene un código JMH como este (tenga en cuenta que estoy usando el mismo distintivo distinto de KeyKey mencionado en la respuesta aceptada):
@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();
}
Entonces tendrás resultados de referencia como este:
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
Y como puede ver, un For-Each simple es 3 veces mejor en rendimiento y menos en puntaje de error en comparación con Java 8 Stream.
Mayor rendimiento, mejor rendimiento
Function<? super T, ?>
, noFunction<? super T, Object>
. También debe tenerse en cuenta que para la secuencia paralela ordenada, esta solución no garantiza qué objeto se extraerá (a diferencia de lo normaldistinct()
). También para las secuencias secuenciales hay una sobrecarga adicional en el uso de CHM (que está ausente en la solución @nosid). Finalmente, esta solución viola el contrato delfilter
método cuyo predicado debe ser sin estado como se indica en JavaDoc. Sin embargo, votó positivamente.