在hashmap中,如果存在重复值,如何将上一个键分配给下一个键

时间:2018-01-27 18:27:15

标签: java collections hashmap

我试图将以前的密钥分配给下一个密钥,以防重复出现在hashmap中。

例如,hashmap中的重复条目:

5-->51  
6-->51

我想要输出如下:

5-->51  
5-->51

以下是我的代码:

HashMap<Integer, Integer> map = new HashMap();
    map.put(1, 99);
    map.put(2, 120);
    map.put(3, 89);
    map.put(4, 71);
    map.put(5, 51);
    map.put(6, 51);
    map.put(7, 77);
    map.put(8, 44);
    map.put(9, 22);
    Set set = new HashSet<>();
    List list = new ArrayList<>();
    for (Entry<Integer, Integer> mapVal : map.entrySet()) {
        if (!set.add(mapVal.getValue())) {
            list.add(mapVal.getValue());
        } else {
            set.add(mapVal.getValue());
        }
    }
    for (Entry<Integer, Integer> mapVal : map.entrySet()) {
        if (list.contains(mapVal.getValue())) {
            System.out.println(mapVal.getKey() + "-->" + mapVal.getValue());
        }
    }

在hashmap案例中是否可能?如果是这样,我应该使用什么算法或代码?

3 个答案:

答案 0 :(得分:3)

如果我的问题是对的。无论地图中是哪个地图,都无法在地图中使用重复的关键字。你想要两个值相同的密钥,这是不可能的。

答案 1 :(得分:1)

  

我想要输出如下:

5-->51
5-->51

你无法通过Map得到这样的东西,因为键是唯一的。

作为在输出中获得该结果的变通方法,您应该使用Map实现来维护元素的插入顺序:LinkedHashMap
HashMap无法维护它。

然后这个想法很简单:

  • 从地图键创建列表,并根据地图值创建另一个列表。
  • 迭代值列表并更新键列表的元素,其中关联的值包含已遇到的值。
  • 输出列表

以下是示例代码:

public class Foo {

    public static void main(String[] args) {

        HashMap<Integer, Integer> map = new LinkedHashMap<>();
        map.put(1, 99);
        map.put(2, 120);
        map.put(3, 89);
        map.put(4, 71);
        map.put(5, 51); // 51 value
        map.put(6, 51); // 51 value
        map.put(7, 77);
        map.put(8, 51); // 51 value
        map.put(9, 22);

        List<Integer> keys = new ArrayList<>(map.keySet());
        List<Integer> values = new ArrayList<>(map.values());

        Set<Integer> valuesWithKeyUpdated = new HashSet<>();
        for (int i = 0; i < values.size() - 1; i++) {

            final Integer oldestKeyForCurrentValue = keys.get(i);
            final Integer currentValue = values.get(i);

            if (valuesWithKeyUpdated.contains(currentValue)) {
                continue;
            }

            for (int j = 1; j < values.size(); j++) {
                if (currentValue == values.get(j)) {
                    keys.set(j, oldestKeyForCurrentValue);
                }
            }

            valuesWithKeyUpdated.add(values.get(i));
        }


        for (int i = 0; i < keys.size(); i++) {
            System.out.println("key=" + keys.get(i) + ", value="+ values.get(i));

        }
    }
}
  

key = 1,value = 99

     

key = 2,value = 120

     

key = 3,value = 89

     

key = 4,value = 71

     

key = 5,value = 51 //值51,原始地图中的键5

     

key = 5,value = 51 // value 51:显示5而不是6

     

key = 7,value = 77

     

key = 5,value = 51 // value 51:显示5而不是8

     

key = 9,value = 22

答案 2 :(得分:0)

正如@ AliOmar62指出的那样,你不能在地图中拥有重复的密钥。

您可以做的是使用值反转键并将所有值收集到集合中,例如

    Map<Integer, List<Integer>> sameValueToDiffKeys = map.entrySet()
            .stream()
            .map(e -> new SimpleImmutableEntry<>(e.getValue(), e.getKey()))
            .collect(Collectors.toMap(SimpleImmutableEntry::getKey, e -> new ArrayList<>(Collections.singleton(e.getValue())), (first, second) -> {
                first.addAll(second);
                return first;
            }));

您的数据输出将在控制台中显示如下:

{51=[5, 6], 99=[1], 22=[9], 71=[4], 120=[2], 89=[3], 44=[8], 77=[7]}

请查看合并功能,这是Collectors.toMap的第三个参数。

此功能通过将一个键合并到一个集合中来解决所有重复项。