Java 8 Pemungut ke Peta

1. Pengenalan

Dalam tutorial ini cepat, kita akan bercakap tentang toMap () kaedah yang Pengumpul kelas. Kami akan menggunakannya untuk mengumpulkan aliran ke contoh Peta .

Untuk semua contoh yang dibahas di sini, kami akan menggunakan senarai buku sebagai titik permulaan dan mengubahnya menjadi implementasi Peta yang berbeza .

2. Senaraikan ke Peta

Kita akan mulakan dengan kes yang paling mudah, dengan mengubah Senarai menjadi Peta .

Kelas Buku kami ditakrifkan sebagai:

class Book { private String name; private int releaseYear; private String isbn; // getters and setters }

Dan kami akan membuat senarai buku untuk mengesahkan kod kami:

List bookList = new ArrayList(); bookList.add(new Book("The Fellowship of the Ring", 1954, "0395489318")); bookList.add(new Book("The Two Towers", 1954, "0345339711")); bookList.add(new Book("The Return of the King", 1955, "0618129111"));

Untuk senario ini, kami akan menggunakan kaedah toMap () yang berlebihan berikut :

Collector
    
      toMap(Function keyMapper, Function valueMapper)
    

Dengan toMap , kita dapat menunjukkan strategi bagaimana mendapatkan kunci dan nilai untuk peta:

public Map listToMap(List books) { return books.stream().collect(Collectors.toMap(Book::getIsbn, Book::getName)); }

Dan kami dapat mengesahkannya dengan mudah dengan:

@Test public void whenConvertFromListToMap() { assertTrue(convertToMap.listToMap(bookList).size() == 3); }

3. Menyelesaikan Konflik Utama

Contoh di atas berfungsi dengan baik, tetapi apa yang akan berlaku sekiranya terdapat kunci pendua?

Mari kita bayangkan bahawa kita memasukkan Peta kita pada setiap tahun pelepasan Buku :

public Map listToMapWithDupKeyError(List books) { return books.stream().collect( Collectors.toMap(Book::getReleaseYear, Function.identity())); }

Memandangkan senarai buku kami yang terdahulu, kami akan melihat IllegalStateException :

@Test(expected = IllegalStateException.class) public void whenMapHasDuplicateKey_without_merge_function_then_runtime_exception() { convertToMap.listToMapWithDupKeyError(bookList); }

Untuk menyelesaikannya, kita perlu menggunakan kaedah yang berbeza dengan parameter tambahan, fungsi merge :

Collector toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction) 

Mari memperkenalkan fungsi penggabungan yang menunjukkan bahawa, sekiranya berlaku perlanggaran, kami menyimpan entri yang ada:

public Map listToMapWithDupKey(List books) { return books.stream().collect(Collectors.toMap(Book::getReleaseYear, Function.identity(), (existing, replacement) -> existing)); }

Atau, dengan kata lain, kita mendapat tingkah laku kemenangan pertama:

@Test public void whenMapHasDuplicateKeyThenMergeFunctionHandlesCollision() { Map booksByYear = convertToMap.listToMapWithDupKey(bookList); assertEquals(2, booksByYear.size()); assertEquals("0395489318", booksByYear.get(1954).getIsbn()); }

4. Jenis Peta Lain

Secara lalai, kaedah toMap () akan mengembalikan HashMap .

Tetapi bolehkah kita mengembalikan pelaksanaan Peta yang berbeza ? Jawapannya adalah ya:

Collector toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction, Supplier mapSupplier)

Di mana mapSupplier adalah fungsi yang mengembalikan Peta kosong baru dengan hasilnya.

4.1. Senaraikan ke Peta Bersama

Mari kita ambil contoh yang sama seperti di atas dan tambahkan fungsi mapSupplier untuk mengembalikan ConcurrentHashMap:

public Map listToConcurrentMap(List books) { return books.stream().collect(Collectors.toMap(Book::getReleaseYear, Function.identity(), (o1, o2) -> o1, ConcurrentHashMap::new)); }

Mari teruskan dan uji kod kami:

@Test public void whenCreateConcurrentHashMap() { assertTrue(convertToMap.listToConcurrentMap(bookList) instanceof ConcurrentHashMap); }
4.2. Peta disusun

Terakhir, mari kita lihat cara mengembalikan peta yang disusun. Untuk itu kami akan menggunakan TreeMap sebagai parameter mapSupplier .

Oleh kerana TreeMap disusun mengikut urutan semula jadi kuncinya secara lalai, kami tidak perlu menyusun buku secara eksplisit :

public TreeMap listToSortedMap(List books) { return books.stream() .collect( Collectors.toMap(Book::getName, Function.identity(), (o1, o2) -> o1, TreeMap::new)); }

Jadi dalam kes kami, TreeMap yang dikembalikan akan disusun mengikut urutan abjad mengikut nama buku:

@Test public void whenMapisSorted() { assertTrue(convertToMap.listToSortedMap(bookList).firstKey().equals( "The Fellowship of the Ring")); }
5. Kesimpulan

Dalam artikel ini, kita melihat ke dalam toMap () kaedah yang Pengumpul kelas. Ini membolehkan kita membuat Peta baru dari Aliran . Kami juga belajar bagaimana menyelesaikan konflik utama dan membuat implementasi peta yang berbeza.

Seperti biasa kodnya tersedia di GitHub.