如何使用Map <string,t =“”>在Java中创建递归树状数据结构?

时间:2019-02-18 08:35:26

标签: java recursive-datastructures

尝试创建遵循该模式的数据结构时,我有一个思路障碍:

Map<String, T>是主要组成部分,TMap<String, T>或作为终端运营商List<String>。是否有可能在Java中构建任何类似的东西,这个想法来自F#或类似Haskell之类的功能语言。

我搜索了SO,但到目前为止在Java中找不到与我的想法相符的内容。

4 个答案:

答案 0 :(得分:4)

是:您可以执行以下操作:

public abstract class T {
...
}
public class NonTerminal extends T {
    private Map<String,T> map = new HashMap<>();
...
}
public class Terminal extends T {
    private List<String> list;
---
}

答案 1 :(得分:3)

用Java重新创建函数式编程并不是一个好主意(至少在Java 8中不是,我对Java 11不了解)。

您可以执行以下操作:

class EitherMapOrList {
    private Map<String, EitherMapOrList> map;
    private List<String> list;

    public EitherMapOrList(Map<String, EitherMapOrList> map) {
        this.map = map;
    }

    public EitherMapOrList(List<String> list) {
        this.list = list;
    }
    // you can remove the optionals here and use null directly.
    public Optional<Map<String, EitherMapOrList>> getMap() {
        return Optional.ofNullable(map);
    }

    public Optional<List<String>> getList() {
        return Optional.ofNullable(list);
    }
}

然后创建一个Map<String, EitherMapOrList>

但是我想在Java中使用此东西会很痛苦。

答案 2 :(得分:3)

您可以仅使用一个Map<String, KeyOrValue>,其中值可以是具有两种实现方式的标记接口

interface KeyOrValue {}

class Key implements KeyOrValue {
    private String key;
}

class Value implements KeyOrValue {
    private List<String> values;
}

然后您可以创建一个查找方法,该方法递归地调用自身,并在到达末尾时返回该值:

private final Map<String, KeyOrValue> map = ...

public List<String> getValues(String key) {
    KeyOrValue keyOrValue = map.get(key);
    if(keyOrValue instanceof Key) {
        // is a key, so use recursion to get the value
        key = ((Key) keyOrValue).key;
        return getValues(key);
    } else if(keyOrValue instanceof Value) {
        // is a value, so just return the value it holds
        return ((Value) keyOrValue).values;
    } else {
        // no mapping was found for "key"
        return null;
    }
}

您也可以不递归地做同样的事情:

public List<String> getValues(String key) {
    KeyOrValue keyOrValue;
    List<String> values = null;
    do {
        keyOrValue = map.get(key);
        if(keyOrValue instanceof Key) {
            // is a key, so iterate further
            key = ((Key) keyOrValue).key;
        } else if(keyOrValue instanceof Value) {
            // is a value, so get the values out and set the key to null to break the loop
            values = ((Value) keyOrValue).values;
            key = null;
        }
    } while(key != null);

    // return the values, may be null due to nothing being found
    return values;
}

虽然实际上并不需要标记接口,但是如果只使用Map<String, Object>,则可以得到相同的结果,其中值可以是StringList<String>,然后是{ {1}}的支票也必须进行调整,但我更喜欢这种方法,instanceof更多

答案 3 :(得分:2)

如果您要翻译haskell

data Map a = Branch { key :: String, value :: a, left :: Map a, right :: Map a} | MapNul

对于Java,您可以使用:

class Map<T> {
    String key;
    T value;
    Map<T> left;
    Map<T> right;
} 

在Java中,您不需要MapNul,因为您可以使用null代替它。