有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在使用流生成映射时忽略重复项

Map<String, String> phoneBook = people.stream()
                                      .collect(toMap(Person::getName,
                                                     Person::getAddress));

当发现重复的元素时,我得到java.lang.IllegalStateException: Duplicate key

在向映射添加值时是否可以忽略此类异常

当存在重复项时,只需忽略该重复项即可继续


共 (6) 个答案

  1. # 1 楼答案

    我在对对象进行分组时遇到过这样的问题,我总是用一种简单的方法来解决它们:使用java执行自定义过滤器。util。设置为删除重复的对象,无论您选择什么属性,如下所示

    Set<String> uniqueNames = new HashSet<>();
    Map<String, String> phoneBook = people
                      .stream()
                      .filter(person -> person != null && !uniqueNames.add(person.getName()))
                      .collect(toMap(Person::getName, Person::getAddress));
    

    希望这能帮助任何有同样问题的人

  2. # 2 楼答案

    @alaster答案对我帮助很大,但如果有人试图对信息进行分组,我想添加一些有意义的信息

    例如,如果您有两个Orders具有相同的code但不同的quantity产品,并且您的愿望是对数量求和,您可以:

    List<Order> listQuantidade = new ArrayList<>();
    listOrders.add(new Order("COD_1", 1L));
    listOrders.add(new Order("COD_1", 5L));
    listOrders.add(new Order("COD_1", 3L));
    listOrders.add(new Order("COD_2", 3L));
    listOrders.add(new Order("COD_3", 4L));
    
    listOrders.collect(Collectors.toMap(Order::getCode, 
                                        o -> o.getQuantity(), 
                                        (o1, o2) -> o1 + o2));
    

    结果:

    {COD_3=4, COD_2=3, COD_1=9}
    

    或从javadocs组合地址:

     Map<String, String> phoneBook
         people.stream().collect(toMap(Person::getName,
                                       Person::getAddress,
                                       (s, a) -> s + ", " + a));
    
  3. # 3 楼答案

    用于按对象分组

    Map<Integer, Data> dataMap = dataList.stream().collect(Collectors.toMap(Data::getId, data-> data, (data1, data2)-> {LOG.info("Duplicate Group For :" + data2.getId());return data1;}));
    
  4. # 4 楼答案

    这可以使用^{}mergeFunction参数来实现:

    Map<String, String> phoneBook = 
        people.stream()
              .collect(Collectors.toMap(
                 Person::getName,
                 Person::getAddress,
                 (address1, address2) -> {
                     System.out.println("duplicate key found!");
                     return address1;
                 }
              ));
    

    mergeFunction是一个对与同一个键关联的两个值进行操作的函数adress1对应于收集元素时遇到的第一个地址,adress2对应于遇到的第二个地址:这个lambda只告诉保留第一个地址,而忽略第二个地址

  5. # 5 楼答案

    JavaDocs所述:

    If the mapped keys contains duplicates (according to Object.equals(Object)), an IllegalStateException is thrown when the collection operation is performed. If the mapped keys may have duplicates, use toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction) instead.

    所以你应该用^{}来代替。只需提供一个合并功能,该功能将确定在地图中放置哪一个副本

    例如,如果你不在乎哪一个,只要打电话就行了

    Map<String, String> phoneBook = 
            people.stream()
                  .collect(Collectors.toMap(Person::getName, 
                                            Person::getAddress, 
                                            (a1, a2) -> a1));
    
  6. # 6 楼答案

    对于遇到此问题但在映射流中没有重复键的任何其他人,确保keyMapper函数没有返回空值

    跟踪这一点非常烦人,因为当它处理第二个元素时,异常会说“复制键1”,而1实际上是条目的值而不是键

    在我的例子中,我的keyMapper函数试图在不同的映射中查找值,但由于字符串中的键入错误,返回的是null值

    final Map<String, String> doop = new HashMap<>();
    doop.put("a", "1");
    doop.put("b", "2");
    
    final Map<String, String> lookup = new HashMap<>();
    doop.put("c", "e");
    doop.put("d", "f");
    
    doop.entrySet().stream().collect(Collectors.toMap(e -> lookup.get(e.getKey()), e -> e.getValue()));