• Java 8 Collectors to Map


    1. 介绍

    在本教程中,我们将讨论Collectors类的toMap()方法。我们使用它将流收集到一个Map实例中。

    对于本教程中涉及的所有示例,我们将使用图书列表作为数据源,并将其转换为不同的Map实现。

    2. List 转换 Map

    我们将从最简单的情况开始,将List 转换 Map

    Book类定义如下:

    class Book {
        private String name;
        private int releaseYear;
        private String isbn;
        //getters and setters
    }
    复制代码

    接着,我们将创建一个List<Book>来验证我们的代码:

    List<Book> 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"));
    复制代码

    对于这个场景,我们将使用以下重载的toMap()方法:

    Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
      Function<? super T, ? extends U> valueMapper)
    复制代码

    使用Collectors.toMap(), 我们将会得到一个Map<String,String>,其中key是isbn的值,value为name的值。

    public Map<String, String> listToMap(List<Book> books) {
        return books.stream().collect(Collectors.toMap(Book::getIsbn, Book::getName));
    }
    复制代码

    我们使用单元测试来验证一下代码:

    @Test
    public void whenConvertFromListToMap() {
        assertTrue(convertToMap.listToMap(bookList).size() == 3);//true
    }
    复制代码

    3. 解决 Key 的冲突

    上面的例子运行得很好,但是如果有一个重复的key会发生什么呢?

    让我们来想象一下,我们将每本图书的出版年份作为key,转换到Map<Integer, Book>中。

    public Map<Integer, Book> listToMapWithDupKeyError(List<Book> books) {
        return books.stream().collect(Collectors.toMap(Book::getReleaseYear, Function.identity()));
    }
    复制代码

    鉴于我们上面的例子,我们会看到一个IllegalStateException的异常:

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

    要解决这个问题,我们需要使用另一种toMap()方法,附加一个参数,mergeFunction:

    Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
      Function<? super T, ? extends U> valueMapper,
      BinaryOperator<U> mergeFunction)
    复制代码

    让我们引入一个merge函数,它表明,在发生冲突的情况下,我们保留现有的元素:

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

    或者,换句话说,我们获得了未发生异常的元素:

    @Test
    public void whenMapHasDuplicateKeyThenMergeFunctionHandlesCollision() {
        Map<Integer, Book> booksByYear = convertToMap.listToMapWithDupKey(bookList);
        assertEquals(2, booksByYear.size());
        assertEquals("0395489318", booksByYear.get(1954).getIsbn());
    }
    复制代码

    4. 其他Map类型

    默认情况下,toMap()方法将返回一个HashMap。 但是我们也可以返回不同的Map实现。

    Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
      Function<? super T, ? extends U> valueMapper,
      BinaryOperator<U> mergeFunction,
      Supplier<M> mapSupplier)
    复制代码

    其中mapSupplier是一个函数,它返回一个新的、带有结果的空Map

    4.1. List 转换 ConcurrentMap

    让我们以上面的例子为例,添加一个mapSupplier函数来返回一个ConcurrentHashMap:

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

    下面我们测试一下

    @Test
    public void whenCreateConcurrentHashMap() {
        assertTrue(convertToMap.listToConcurrentMap(bookList) instanceof ConcurrentHashMap);
    }
    复制代码

    4.2. List 转换 SortedMap

    最后,让我们看看如何返回一个排序后的Map。为此,我们需要对List<Book>进行排序,并使用TreeMap作为mapSupplier参数:

    public TreeMap<String, Book> listToSortedMap(List<Book> books) {
        return books.stream() 
          .sorted(Comparator.comparing(Book::getName))
          .collect(Collectors.toMap(Book::getName, Function.identity(), (o1, o2) -> o1, TreeMap::new));
    }
    复制代码

    上面的代码将List<Book>按照书名进行排序,然后将结果收集到TreeMap<String, Book>中:

    @Test
    public void whenMapisSorted() {
        assertTrue(convertToMap.listToSortedMap(bookList).firstKey().equals("The Fellowship of the Ring"));
    }
    复制代码

    5. 结论

    在本文中,我们研究了Collectors类的toMap()方法。它允许我们从一个流创建一个新的Map。我们还学习了如何解决key冲突和创建不同的Map实现。

    代码可以在GitHub中找到。

    原文链接:www.baeldung.com/java-collec…

    作者:Rodrigo Graciano

    译者:李东


    作者:锅外的大佬
    链接:https://juejin.im/post/5d06f11b5188252a71629c7b
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    Mysql group_concat
    canvas toDataUrl 跨域问题
    Svg操作
    java 判断浏览器
    排序操作
    java 格式判断
    你真的了解 console 吗
    svg转换工具
    java图片缩放
    常见 银行贷款 名词
  • 原文地址:https://www.cnblogs.com/liululee/p/11038072.html
Copyright © 2020-2023  润新知