[英]How to create recursive tree-like data structure in java using Map<String, T>?
I have a mind-block when trying to create data-structure that follows the pattern: 在尝试创建遵循模式的数据结构时,我有一个思维模块:
Map<String, T>
is a main building block and T
is either Map<String, T>
or as terminal operator List<String>
. Map<String, T>
是主要构建块, T
是Map<String, T>
或者是终端运算符List<String>
。 Is it possible to build anything similar in Java
, this idea comes from functional languages like F#
or Haskell
-like. 是否有可能在
Java
构建类似的东西,这个想法来自F#
或Haskell
类的函数式语言。
I searched SO
but so far couldn't find anything that match my idea in Java
. 我搜索了
SO
但到目前为止找不到任何符合我的想法的Java
。
Yes: you can do something like this: 是的:你可以这样做:
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;
---
}
Recreating functional programming stuff in Java isn't really a good idea (at least not in Java 8, I don't know about Java 11). 在Java中重新创建函数式编程并不是一个好主意(至少在Java 8中,我不了解Java 11)。
You can do something like this: 你可以这样做:
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);
}
}
And then create a Map<String, EitherMapOrList>
. 然后创建一个
Map<String, EitherMapOrList>
。
But I would imagine it would be a pain to use this thing in Java. 但我想在Java中使用这个东西会很痛苦。
You could use just a single Map<String, KeyOrValue>
where the value could be a marker interface with two implementations 您可以只使用一个
Map<String, KeyOrValue>
,其中值可以是具有两个实现的标记接口
interface KeyOrValue {}
class Key implements KeyOrValue {
private String key;
}
class Value implements KeyOrValue {
private List<String> values;
}
You could then just create a lookup method which recursivly calls itself and then returns the value once it has reached the end: 然后,您可以创建一个recursivly调用自身的查找方法,然后在到达结尾时返回该值:
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;
}
}
You could do the same without recursion too: 你也可以在没有递归的情况下做同样的事情:
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;
}
The marker interface is not really needed though, you can get the same outcome if you just use Map<String, Object>
where the value could either be a String
or a List<String>
and then the instanceof
checks would have to be adapted too, but I like the approach the way with an interface
more 但是,实际上并不需要标记接口,如果只使用
Map<String, Object>
,则可以得到相同的结果Map<String, Object>
其中值可以是String
或List<String>
,然后也必须调整instanceof
检查,但我更喜欢interface
的方式
If you want to translate haskell 如果你想翻译haskell
data Map a = Branch { key :: String, value :: a, left :: Map a, right :: Map a} | MapNul
to java you can go with: 你可以去java:
class Map<T> {
String key;
T value;
Map<T> left;
Map<T> right;
}
you do not need MapNul
in java because you can use null
instead of it. 你不需要在java中使用
MapNul
,因为你可以使用null
而不是它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.