如何修改/删除作为HashMap中元素的两个ArrayList?

时间:2019-09-22 12:00:37

标签: java arraylist hashmap illegalstateexception concurrentmodification

说明

我有一个HashMap<ArrayLists<Integer>, <Integer>>,类似于以下({Key=Value}):

{[1]=1, [3]=1, [1, 4, 6]=1, [0, 2, 3, 5, 6]=3, [6]=1}

我需要比较然后修改/删除其他ArrayLists中的元素(即HashMap中的元素),直到满足以下条件:

  1. 每个ArrayList元素仅属于一个列表,该列表具有最高的Value
  2. 如果Value = 1用于包含该元素的所有列表,则ArrayList元素属于单例列表。
  3. 如果ArrayList为空,则应将其从HashMap中删除。

因此,对于上面的示例,它应该以以下内容结束:

{[1]=1, [4]=1, [0, 2, 3, 5, 6]=3}

我曾经使用过数组的数组来做这样的事情。这次具有HashMapArrayList的功能将是实用的,但是我目前不愿意对这些数据类型进行更复杂的修改。我做了几次尝试,不得不同时阻止ConcurrentModificationExceptionIllegalStateException,但是还没有完全成功。我也感觉到我的实现变得不必要的复杂,因此,如果有这样的经验的人来实现,我将不胜感激。


关于HashMap

的注释

我使用HashMap的原因(可以提出一些更合适的建议)是因为ValueArrayList被“遇到”并添加了多少次的计数到HashMap


最小示例

我最近的无效(IndexOutOfBoundsException)尝试的最小示例。请注意,HashMapArrayList的创建在这里是静态完成的,因为在我的真实程序中,它是基于文件内容不确定地完成的。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Test {
    public static void main(String[] args) {
        Map<List<Integer>, Integer> example = new HashMap<>(7);
        List<Integer> list = new ArrayList<>(7);
        list.add(1);
        example.put(list, 1);
        list = new ArrayList<>(7);
        list.add(3);
        example.put(list, 1);
        list = new ArrayList<>(7);
        list.add(1);
        list.add(4);
        list.add(6);
        example.put(list, 1);
        list = new ArrayList<>(7);
        list.add(0);
        list.add(2);
        list.add(3);
        list.add(5);
        list.add(6);
        example.put(list, 3);
        list = new ArrayList<>(7);
        list.add(6);
        example.put(list, 1);
        System.err.println(example);

        Map<List<Integer>, Integer> copy = new HashMap<>(example);
        for (Map.Entry<List<Integer>, Integer> outer : example.entrySet()) {
            for (Map.Entry<List<Integer>, Integer> inner : copy
                .entrySet()) {
                for (int i : outer.getKey()) {
                    int oSize = outer.getKey().size();
                    int iSize = inner.getKey().size();
                    int oValue = outer.getValue();
                    int iValue = inner.getValue();

                    if (!(inner.equals(outer)) && (inner.getKey()
                        .contains(i))) {
                        if (oSize == 1) {
                            if (oValue < iValue) {
                                outer.getKey().remove(i);
                            } else {
                                inner.getKey().remove(i);
                            }
                        } else if (iSize == 1) {
                            if (iValue < oValue) {
                                outer.getKey().remove(i);
                            } else {
                                inner.getKey().remove(i);
                            }
                        } else {
                            if (oValue < iValue) {
                                outer.getKey().remove(i);
                            } else {
                                inner.getKey().remove(i);
                            }
                        }
                    }
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:2)

使用ArrayList作为HashMap(Are mutable hashmap keys a dangerous practice?)的键非常不寻常。 但是,假设您对此没有问题,则要更新Map条目,可以从hasmap中删除该条目(List和整数),创建具有更改的新List,然后在必要时重新插入。

答案 1 :(得分:2)

在我看来,我建议在第一轮中对地图值(按照最高值)进行排序,然后使用业务逻辑完成删除工作。

例如:

        Map<List<Integer>, Integer> example = new HashMap<>();
        // data initialize

        // order by Map.Entry::getValue desc
        List<Map.Entry<List<Integer>, Integer>> collect = example.entrySet()
                .stream()
                .sorted((e1, e2) -> e2.getValue() - e1.getValue())
                .collect(Collectors.toList());

        // remove duplicate list element in Map.Entry::getKey
        Set<Integer> tmp = new HashSet<>();
        // collect.forEach(c -> c.getKey().removeIf(next -> !tmp.add(next)));
        example = collect
                .stream()
                .filter(c -> {
                    c.getKey().removeIf(next -> !tmp.add(next));
                    return !c.getKey().isEmpty();
                })
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));