zoukankan      html  css  js  c++  java
  • 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
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    openwrt 相关文章
    负载均衡相关文章
    Today's Progress
    Rodrigues formula is beautiful, but uneven to sine and cosine. (zz Berkeley's Page)
    Camera Calibration in detail
    Fundamental Matrix in Epipolar
    Camera Calibration's fx and fy do Cares in SLAM
    FilterEngine::apply
    FilterEngine 类解析——OpenCV图像滤波核心引擎(zz)
    gaussBlur
  • 原文地址:https://www.cnblogs.com/liululee/p/11038072.html
Copyright © 2011-2022 走看看