如何使用 Map<String, T> 在 java 中创建递归树状数据结构?
How to create recursive tree-like data structure in java using Map<String, T>?
我在尝试创建遵循以下模式的数据结构时遇到了障碍:
Map<String, T>
是主要构建块,T
是 Map<String, T>
或终端运算符 List<String>
。是否有可能在 Java
中构建任何类似的东西,这个想法来自函数式语言,如 F#
或 Haskell
-like.
我搜索了 SO
,但到目前为止在 Java
中找不到符合我想法的内容。
是的:你可以这样做:
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;
---
}
在 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中使用这个东西会很痛苦。
如果要翻译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
代替它。
您可以只使用一个 Map<String, KeyOrValue>
,其中值可以是具有两个实现的标记接口
interface KeyOrValue {}
class Key implements KeyOrValue {
private String key;
}
class Value implements KeyOrValue {
private List<String> values;
}
然后您可以只创建一个查找方法,该方法递归调用自身,然后 returns 到达末尾后的值:
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>
可以得到相同的结果,其中值可以是 String
或 List<String>
然后instanceof
检查也必须进行调整,但我喜欢使用 interface
more
的方法
我在尝试创建遵循以下模式的数据结构时遇到了障碍:
Map<String, T>
是主要构建块,T
是 Map<String, T>
或终端运算符 List<String>
。是否有可能在 Java
中构建任何类似的东西,这个想法来自函数式语言,如 F#
或 Haskell
-like.
我搜索了 SO
,但到目前为止在 Java
中找不到符合我想法的内容。
是的:你可以这样做:
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;
---
}
在 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中使用这个东西会很痛苦。
如果要翻译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
代替它。
您可以只使用一个 Map<String, KeyOrValue>
,其中值可以是具有两个实现的标记接口
interface KeyOrValue {}
class Key implements KeyOrValue {
private String key;
}
class Value implements KeyOrValue {
private List<String> values;
}
然后您可以只创建一个查找方法,该方法递归调用自身,然后 returns 到达末尾后的值:
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>
可以得到相同的结果,其中值可以是 String
或 List<String>
然后instanceof
检查也必须进行调整,但我喜欢使用 interface
more