如何递归读取Java地图

时间:2019-02-08 15:13:01

标签: java dictionary recursion

我有如下的Java映射。我想读取所有值,其中键可以是其他键的值。在这里,我试图写一些反响方法来读取它,但是没有运气。如果有人有经验,请给我解释。

Map map= new HashMap();
map.put("a", "1");
map.put("b", "2");
map.put("c", "3");
map.put("1", "4");
map.put("4", "5");

在上图中,如果我通过"a"作为键,我希望与1,4,5对应的所有值

3 个答案:

答案 0 :(得分:2)

假设您没有任何循环:

private String mapRecursion(Map<String,String> map, String key) {
    String s = map.get(key);
    if (map.get(s) == null) {
        return s;
    }
    return s + "," + mapRecursion(map, s);
}

答案 1 :(得分:1)

您可以通过从一个键开始并返回带有其值的方法调用来递归地导航地图。

import java.util.*;

public class RecurseMap {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("a", "1");
        map.put("b", "2");
        map.put("c", "3");
        map.put("1", "4");
        map.put("4", "5");
        map.put("5", "a"); // Circular reference!

        navigate(map, "a");
    }

    public static <K, V> void navigate(Map<K, V> map, K key) {
        navigate(map, key, new TreeSet<K>());
    }

    @SuppressWarnings("unchecked")
    public static <K, V> void navigate(Map<K, V> map, K key, Set<K> visited) {
        System.out.println(String.format("Current key: %s", key));
        if (!visited.contains(key) && map.containsKey(key)) {
            visited.add(key);
            navigate(map, (K) map.get(key), visited);
        }
    }
}

输出

Current key: a
Current key: 1
Current key: 4
Current key: 5
Current key: a

请记住,方法签名应该是<K, K><K>,但是我在上面使用<K, V>来表示键,值的关系。

public static <K> void navigate(Map<K, K> map, K key) {
    navigate(map, key, new TreeSet<K>());
}

public static <K> void navigate(Map<K, K> map, K key, Set<K> visited) {
    System.out.println(String.format("Current key: %s", key));
    if (!visited.contains(key) && map.containsKey(key)) {
        visited.add(key);
        navigate(map, (K) map.get(key), visited);
    }
}

漫步地图

更新:您可以创建一个访问者类来评估地图键/值。

import java.util.*;

public class RecurseMap {
    private static interface Visitor<K> {
        void visit(K key, K value, Map<K, K> map);
    }

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("a", "1");
        map.put("b", "2");
        map.put("c", "3");
        map.put("1", "4");
        map.put("4", "5");
        map.put("5", "a"); // Circular reference!

        walkMap(map, "a", new Visitor<String>() {
            @Override
            public void visit(String key, String value, Map<String, String> mapRef) {
                System.out.println(String.format("Current key: %s", key));
            }
        });
    }

    public static <K> void walkMap(Map<K, K> map, K key, Visitor<K> visitor) {
        walkMap(map, key, visitor, new TreeSet<K>());
    }

    public static <K> void walkMap(Map<K, K> map, K key, Visitor<K> visitor, Set<K> visited) {
        if (!visited.contains(key) && map.containsKey(key)) {
            K value = map.get(key);
            visitor.visit(key, value, map);
            visited.add(key);
            walkMap(map, value, visitor, visited);
        }
    }
}

答案 2 :(得分:0)

为防止Java.lang.StackOverflowError,如果映射中发生循环,则可以检查该值是否已存在,然后将continer(此处为Set)提供给该方法,而不让该方法自己创建

static Set<String> getValues(Map<String, String> map, String key, Set<String> res) {
    String val = map.get(key);
    if (val != null && !res.contains(val)) {
        res.add(val);
        res.addAll(getValues(map, val, res));
    }
    return res;
}

//Use as 
Set<String> res = getValues(map, "a", new HashSet<>());
System.out.println(res);