Enquanto a resposta mais alta votada é absolutamente a melhor resposta em Java 8, é ao mesmo tempo absolutamente pior em termos de desempenho. Se você realmente deseja um aplicativo de baixo desempenho e ruim, vá em frente e use-o. O simples requisito de extrair um conjunto exclusivo de Nomes de Pessoas deve ser alcançado com mero "For-Each" e um "Set". As coisas pioram ainda mais se a lista estiver acima do tamanho 10.
Considere que você tem uma coleção de 20 objetos, assim:
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"));
Onde seu objeto se SimpleEvent
parece com isso:
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 para testar, você tem um código JMH como este (observe que estou usando o mesmo Predicado distintoByKey mencionado na resposta aceita):
@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();
}
Então você terá resultados de benchmark 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
E, como você pode ver, um For-Each simples é 3 vezes melhor em taxa de transferência e menos em pontuação de erro em comparação com o Java 8 Stream.
Maior rendimento, melhor desempenho
Function<? super T, ?>
, nãoFunction<? super T, Object>
. Também deve-se notar que, para o fluxo paralelo ordenado, esta solução não garante qual objeto será extraído (diferente do normaldistinct()
). Também para fluxos sequenciais, há uma sobrecarga adicional no uso do CHM (que está ausente na solução @nosid). Finalmente, esta solução viola o contrato dofilter
método cujo predicado deve ser sem estado, conforme declarado no JavaDoc. Mesmo assim votado.