• Java在Map中存放重复key


    1.概述

    本文介绍几种处理Map中一个key对多个value的方法。在JDK标准Map实现中当我们尝试在一个key下插入多个value,那么后续的value会覆盖前面的value。

    Map<String, String> map = new HashMap<>();
    assertThat(map.put("key1", "value1")).isEqualTo(null);
    assertThat(map.put("key1", "value2")).isEqualTo("value1");
    assertThat(map.get("key1")).isEqualTo("value2");


    2.将集合作为Value

    当要处理一个key对多个value的情况,可以将所有value存放在一个集合中。

    Map<String, List<String>> map = new HashMap<>();
    List<String> list = new ArrayList<>();
    map.put("key1", list);
    map.get("key1").add("value1");
    map.get("key1").add("value2");
     
    assertThat(map.get("key1").get(0)).isEqualTo("value1");
    assertThat(map.get("key1").get(1)).isEqualTo("value2");


    这种方式处理有多种缺点并且容易产生错误。我们需要为每个key创建一个集合,同时检查集合是否存在并添加或删除值,在Java 8中可以利用compute()方法来简化代码。

    Map<String, List<String>> map = new HashMap<>();
    map.computeIfAbsent("key1", k -> new ArrayList<>()).add("value1");
    map.computeIfAbsent("key1", k -> new ArrayList<>()).add("value2");
     
    assertThat(map.get("key1").get(0)).isEqualTo("value1");
    assertThat(map.get("key1").get(1)).isEqualTo("value2");

    3.使用Apache Commons Collections

    添加依赖

    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-collections4</artifactId>
      <version>4.1</version>
    </dependency>

    3.1 MutiMap

    org.apache.commons.collections4.MultiMap接口定义了一个Map,每个key对应一个集合。

    MultiMap<String, String> map = new MultiValueMap<>();
    map.put("key1", "value1");
    map.put("key1", "value2");
    assertThat((Collection<String>) map.get("key1"))
      .contains("value1", "value2");

    这个类非线程安全,4.1版本中已经废弃。
    3.2 MultiValuedMap

    org.apache.commons.collections4.MultiValuedMap这个接口有多种实现,如ArrayListValuedHashMap与HashSetValuedHashMap。

    使用方式如下:

    MultiValuedMap<String, String> map = new ArrayListValuedHashMap<>();
    map.put("key1", "value1");
    map.put("key1", "value2");
    map.put("key1", "value2");
    assertThat((Collection<String>) map.get("key1"))
      .containsExactly("value1", "value2", "value2");

    MultiValuedMap<String, String> map = new HashSetValuedHashMap<>();
    map.put("key1", "value1");
    map.put("key1", "value1");
    assertThat((Collection<String>) map.get("key1"))
      .containsExactly("value1");

    若不希望value重复那么可以使用HashSetValuedHashMap

    MultiValuedMap<String, String> map = new HashSetValuedHashMap<>();
    map.put("key1", "value1");
    map.put("key1", "value1");
    assertThat((Collection<String>) map.get("key1"))
      .containsExactly("value1");

    但ArrayListValuedHashMap,HashSetValuedHashMap及HashSetValuedHashMap都不是线程安全的。为了线程安全可以使用UnmodifiableMultiValuedMap。

    @Test(expected = UnsupportedOperationException.class)
    public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() {
        MultiValuedMap<String, String> map = new ArrayListValuedHashMap<>();
        map.put("key1", "value1");
        map.put("key1", "value2");
        MultiValuedMap<String, String> immutableMap =
          MultiMapUtils.unmodifiableMultiValuedMap(map);
        immutableMap.put("key1", "value3");
    }

    4.Guava Multimap

    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>23.0</version>
    </dependency>

    4.1 LinkedHashMultimap

    这个类按插入顺序存放插入元素

    Multimap<String, String> map = LinkedHashMultimap.create();
    map.put("key1", "value3");
    map.put("key1", "value1");
    map.put("key1", "value2");
    assertThat((Collection<String>) map.get("key1"))
      .containsExactly("value3", "value1", "value2");

    4.2 TreeMultimap

    这个类按可以按自然序访问插入的元素

    Multimap<String, String> map = TreeMultimap.create();
    map.put("key1", "value3");
    map.put("key1", "value1");
    map.put("key1", "value2");
    assertThat((Collection<String>) map.get("key1"))
      .containsExactly("value1", "value2", "value3");

    5.自定义MultiMap

    如果使用Guava,那么还可以使用Multimap.newMultimap()来定制我们的Map。
    6.总结

    一对多思路就是通过集合来存储元素,guava和apache collection为我们提供了现成的工具,如果想自定义还可以使用guava提供的扩展方法来实现。

  • 相关阅读:
    XAF应用开发教程(七)外观控制模块
    XAF应用开发教程(五)验证模块
    XAF应用开发教程(六)控制器
    XAF应用开发教程(四)应用程序模型
    XAF应用开发教程(三)业务对象模型之引用类型与关联关系
    XAF应用开发教程(二)业务对象模型之简单类型属性
    XAF应用开发教程(一) 创建项目
    CSharp Similarities and Differences
    Nemerle Quick Guide
    2.1 确知信号的类型
  • 原文地址:https://www.cnblogs.com/interdrp/p/16516131.html
Copyright © 2020-2023  润新知