Membina Pengumpul Tersuai
Laksanakan antara muka Collector untuk mencipta pengagregatan boleh guna semula bagi kes penggunaan khusus domain.
Membina Pengumpul Tersuai ialah pelajaran Java Academy percuma di CoddyKit. Ini ialah pelajaran 4 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Java Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Java Academy merangkumi sejumlah 4 pelajaran.
Mengapa Membina Pengumpul Tersuai?
Apabila pengumpul terbina dalam tidak sesuai dengan domain anda, laksanakan antara muka Collector<T, A, R> untuk mencipta logik pengagregatan yang boleh diguna semula dan digabungkan. T=masukan, A=pengumpul boleh ubah, R=hasil.
Antara Muka Pengumpul
Pengumpul mempunyai lima komponen:
supplier()— mencipta pengumpul awalaccumulator()— memasukkan satu elemen ke dalam pengumpulcombiner()— menggabungkan dua pengumpul untuk strim selarifinisher()— mengubah pengumpul kepada hasil akhircharacteristics()— petunjuk pengoptimuman
Kilang Collector.of()
Cara paling mudah untuk mencipta pengumpul tersuai ialah menggunakan Collector.of() tanpa melaksanakan antara muka secara langsung:
import java.util.stream.*;
// Collector that builds a comma-separated String
Collector<String, StringBuilder, String> csvCollector = Collector.of(
StringBuilder::new, // supplier
(sb, s) -> {
if (sb.length() > 0) sb.append(',');
sb.append(s);
}, // accumulator
(a, b) -> {
if (a.length() > 0 && b.length() > 0) a.append(',');
a.append(b); return a;
}, // combiner
StringBuilder::toString // finisher
);
String csv = Stream.of("Alice","Bob","Carol").collect(csvCollector);
System.out.println(csv); // Alice,Bob,CarolPengumpul Tersuai: N Teratas
Bina pengumpul yang hanya mengekalkan N elemen teratas berdasarkan pembanding:
import java.util.*;
import java.util.stream.*;
static <T> Collector<T, ?, List<T>> topN(int n, Comparator<T> comp) {
return Collector.of(
() -> new ArrayList<T>(),
(list, e) -> {
list.add(e);
list.sort(comp.reversed());
if (list.size() > n) list.remove(list.size() - 1);
},
(a, b) -> {
a.addAll(b);
a.sort(comp.reversed());
while (a.size() > n) a.remove(a.size() - 1);
return a;
},
Collector.Characteristics.UNORDERED
);
}Menggunakan Pengumpul N Teratas
Gunakan pengumpul N Teratas tersuai pada strim:
List<Integer> top3 = Stream.of(5,2,9,1,7,3,8)
.collect(topN(3, Comparator.naturalOrder()));
System.out.println(top3); // [9, 8, 7]Bendera Ciri
Tiga ciri pilihan melaraskan pengoptimuman strim:
IDENTITY_FINISH— penamat ialah identiti; langkau langkah iniUNORDERED— susunan hasil tidak pentingCONCURRENT— pengumpul boleh dipanggil secara serentak
Menetapkan bendera yang salah, contohnya CONCURRENT tanpa keselamatan benang, menyebabkan pepijat.
Pengumpul Tersuai: Purata Berjalan
Kekalkan purata berjalan tanpa lintasan kedua:
record RunningAvg(long count, double sum) {
RunningAvg add(double v) { return new RunningAvg(count+1, sum+v); }
RunningAvg merge(RunningAvg o) { return new RunningAvg(count+o.count, sum+o.sum); }
double avg() { return count == 0 ? 0 : sum / count; }
}
Collector<Double, RunningAvg[], Double> avgCollector = Collector.of(
() -> new RunningAvg[]{new RunningAvg(0, 0)},
(a, v) -> a[0] = a[0].add(v),
(a, b) -> { a[0] = a[0].merge(b[0]); return a; },
a -> a[0].avg()
);
double avg = Stream.of(10.0, 20.0, 30.0).collect(avgCollector);
System.out.println(avg); // 20.0Melaksanakan Antara Muka Pengumpul Secara Langsung
Untuk kawalan yang lebih besar, laksanakan Collector<T,A,R> sebagai kelas:
import java.util.function.*;
import java.util.stream.*;
class StringJoiningCollector implements Collector<String, List<String>, String> {
private final String delimiter;
StringJoiningCollector(String delimiter) { this.delimiter = delimiter; }
public Supplier<List<String>> supplier() { return ArrayList::new; }
public BiConsumer<List<String>, String> accumulator() { return List::add; }
public BinaryOperator<List<String>> combiner() {
return (a,b) -> { a.addAll(b); return a; };
}
public Function<List<String>, String> finisher() {
return list -> String.join(delimiter, list);
}
public Set<Characteristics> characteristics() { return Set.of(); }
}Membandingkan Pengumpul Tersuai dengan Pengumpul Terbina Dalam
Sebelum menulis pengumpul tersuai, semak sama ada gabungan pengumpul terbina dalam dapat mencapai hasil yang sama — pengumpul tersebut telah diuji dan dioptimumkan:
// Instead of custom, compose:
Map<String, IntSummaryStatistics> stats = orders.stream().collect(
Collectors.groupingBy(Order::status,
Collectors.summarizingInt(Order::amount))
);
// This replaces many custom collector implementationsKeselamatan Benang dalam Pengumpul Tersuai
Jika ciri CONCURRENT ditetapkan, pengumpul dipanggil oleh beberapa benang secara serentak. Oleh itu, pengumpul mestilah selamat untuk benang, contohnya menggunakan ConcurrentHashMap atau AtomicLong. Tanpa CONCURRENT, penggabung mengendalikan pemprosesan selari dengan selamat.
Kes Penggunaan Sebenar: Pengumpul Histogram
Kelompokkan nilai berangka ke dalam peta histogram:
Collector<Integer, Map<Integer, Long>, Map<Integer, Long>> histogram =
Collector.of(
LinkedHashMap::new,
(map, val) -> map.merge(val / 10 * 10, 1L, Long::sum),
(a, b) -> { b.forEach((k,v) -> a.merge(k,v,Long::sum)); return a; },
Collector.Characteristics.IDENTITY_FINISH
);
Map<Integer,Long> hist = Stream.of(5,15,25,12,8,22,18,3)
.collect(histogram);
hist.forEach((bucket, cnt) -> System.out.println(bucket+"-"+(bucket+9)+": "+cnt));Semakan Ringkas
Apakah bendera ciri pengumpul yang menunjukkan bahawa fungsi penamat ialah transformasi identiti dan boleh dilangkau?
Ringkasan: Pengumpul Tersuai
Perkara utama:
- Pengumpul<T,A,R>: T=masukan, A=pengumpul, R=hasil
- Gunakan Collector.of() untuk pelaksanaan pantas tanpa kelas
- pembekal/pengumpul/penggabung/penamat/ciri ialah lima bahagian
- Bendera pengoptimuman: penamat identiti, UNORDERED dan CONCURRENT
- Utamakan gabungan pengumpul terbina dalam; gunakan pengumpul tersuai hanya apabila perlu
Pelajari Java dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 104
- Pelajaran
- 374
Soalan Lazim
Adakah pelajaran “Membina Pengumpul Tersuai” percuma?
Ya — teks penuh “Membina Pengumpul Tersuai” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Java Academy, tingkat taraf kepada CoddyKit PRO. Kursus Java Academy merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Membina Pengumpul Tersuai”?
Laksanakan antara muka Collector untuk mencipta pengagregatan boleh guna semula bagi kes penggunaan khusus domain. Anda berlatih Java Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Java Academy?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Java Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 4 daripada 4.
Berapa lamakah pelajaran “Membina Pengumpul Tersuai” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Java Academy ini?
Ya. Setiap pelajaran Java Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- groupingBy: Mengelaskan Elemen
- partitioningBy dan counting
- toMap, joining dan summarizing
- Membina Pengumpul Tersuai