ในขณะที่คำตอบ upvoted ที่สูงที่สุดคือคำตอบที่ดีที่สุดอย่างแน่นอน wrt Java 8 แต่ในเวลาเดียวกันนั้นแย่ที่สุดในแง่ของประสิทธิภาพ หากคุณต้องการแอปพลิเคชั่นที่มีประสิทธิภาพต่ำให้ใช้งานต่อไป ความต้องการง่าย ๆ ในการแยกชุดชื่อบุคคลที่ไม่ซ้ำกันจะทำได้โดยเพียง "ต่อคน" และ "ตั้ง" สิ่งต่าง ๆ ยิ่งแย่ลงถ้ารายการมีขนาดใหญ่กว่า 10
พิจารณาว่าคุณมีคอลเลกชันวัตถุ 20 ชนิดดังนี้:
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"));
ตำแหน่งที่คุณคัดค้านSimpleEvent
มีลักษณะดังนี้:
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;
}
}
และเพื่อทดสอบคุณมีJMHรหัสเช่นนี้ (โปรดทราบ im ใช้เดียวกันdistinctByKeyกริยาที่กล่าวถึงในคำตอบที่ได้รับการยอมรับ):
@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();
}
จากนั้นคุณจะได้ผลลัพธ์มาตรฐานดังนี้:
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
และอย่างที่คุณเห็นการเรียบง่ายสำหรับแต่ละรายการจะดีกว่า 3 เท่าในปริมาณงานและคะแนนข้อผิดพลาดน้อยกว่าเมื่อเปรียบเทียบกับ Java 8 Stream
ที่สูงขึ้นผ่านที่ดีกว่าผลการดำเนินงาน
Function<? super T, ?>
Function<? super T, Object>
นอกจากนี้ควรสังเกตว่าสำหรับการสตรีมแบบขนานที่มีคำสั่งวิธีนี้จะไม่รับประกันว่าวัตถุใดที่จะถูกแยกออก (ต่างจากปกติdistinct()
) นอกจากนี้สำหรับสตรีมต่อเนื่องจะมีค่าใช้จ่ายเพิ่มเติมสำหรับการใช้ CHM (ซึ่งไม่มีอยู่ใน @nosid solution) ในที่สุดการแก้ปัญหานี้ละเมิดสัญญาของfilter
วิธีการที่จะต้องมีสถานะไร้สัญชาติตามที่ระบุไว้ใน JavaDoc upvoted อย่างไรก็ตาม